【问题标题】:Junit test with multi thread and entity Manager not work使用多线程和实体管理器的 Junit 测试不起作用
【发布时间】:2014-04-17 13:02:20
【问题描述】:

我的客户希望我编写一个测试系统的测试性能。但我对实体管理器有疑问。 我有一种商业方法:

@Transactional(isolation = Isolation.READ_COMMITTED)
public ProductSequence generate(String prefix) {
    if (StringUtils.isBlank(prefix)) {
        throw new IllegalArgumentException("prefix is blank");
    }
    ProductSequence productSequence = new ProductSequence();
    List<ProductSequence> lstProductSequences = getProductSequenceByPrefix(prefix);

    if (!lstProductSequences.isEmpty()) {
        productSequence = lstProductSequences.get(0);
        productSequence.setSequence(productSequence.getSequence() + 1);
        this.entityManager.merge(productSequence);

    } else {
        productSequence.setPrefix(prefix);
        productSequence.setSequence(1L);
        this.entityManager.persist(productSequence);
//want to check again if data was persisted or not 
        List<ProductSequence> lstProductSequences2 = getProductSequenceByPrefix(prefix);
        if (lstProductSequences2.isEmpty()) {
            System.out.println("cannt persist entity manager");
        }

    }
    return productSequence;

}

/**
 * get product list by prefix.
 * 
 * @param prefix
 *            <code>String</code>
 * @return List<ProductSequence>
 */
@Transactional
public List<ProductSequence> getProductSequenceByPrefix(String prefix) {
    TypedQuery<ProductSequence> typedQuery = entityManager.createQuery(
            "SELECT o FROM ProductSequence AS o WHERE o.prefix = :prefix", ProductSequence.class);

    typedQuery.setParameter("prefix", prefix);
    return typedQuery.getResultList();
}

这里是这些方法的测试方法

  final String prefix = "TEST-AUTO";
final List<String> tags = new LinkedList<String>();
@Test
public void testGenerateWithThread() {



    final int loops = 5;

    final int threadCount = 1;

    final CyclicBarrier barrier = new CyclicBarrier(threadCount + 1);

    final boolean[] error = new boolean[] { false };

    Thread[] threads = new Thread[threadCount];
    for (int i = 0; i < threads.length; i++) {
        final int t = i;
        Runnable r = new Runnable() {
            @Override
            @Transactional
            public void run() {
                try {
                    barrier.await();
                } catch (InterruptedException e) {
                    error[0] = true;
                } catch (BrokenBarrierException e) {
                    error[0] = true;
                }
                for (int j = 0; j < loops; j++) {
                    String tagGenerate = productSequence.generate(prefix);
                    tags.add(tagGenerate);
                    System.out.println("In thread " + t + ": " + tagGenerate);
                }
            }
        };
        threads[i] = new Thread(r);
        threads[i].start();
    }

    try {
        barrier.await();
    } catch (InterruptedException e1) {
        System.out.println("Interrupted whilst waiting for barrier");
    } catch (BrokenBarrierException e1) {
        System.out.println("Broken barrier");
    }

    for (int i = 0; i < threads.length; i++) {
        try {
            threads[i].join();
        } catch (InterruptedException e) {
            System.out.println("Interrupted whilst joining thread " + i);
        }
    }

    assertEquals(threadCount * loops, tags.size());
}

/**
 * test for generate function
 */
@Test
@Transactional
public void testGenerateWithoutThread() {
    for (int i = 1; i <= 5; i++) {
        String tagGenerate = productSequence.generate(prefix);
        System.out.println("tag gen " + tagGenerate);
        assertEquals(prefix + "-" + i, tagGenerate);
    }
}

问题是在测试运行时,testGenerateWithoutThread 方法工作正常,但 testGenerateWithThread 无法将数据持久化到内存数据库中。运行 testGenerateWitThread 时标签列表的所有值都是“TEST-AUTO-1”,但在 testGenerateWithoutThread 中将是“TEST-AUTO-1”、“TEST-AUTO-2”、“TEST-AUTO-3”、“TEST-AUTO” -4”,“测试自动 5”。 我不知道为什么?当我运行多线程测试时,实体管理器无法将数据持久化到内存数据库中,但正常方式可以吗?

请帮助我!非常感谢!

【问题讨论】:

  • 既然线程版本只是在循环中执行日志记录,那么它在第二到第五遍的时候在做什么呢?是否有异常导致它退出,它是否挂起?如果你在持久化之后但在查询之前使用 this.entityManager.flush(),会发生什么?

标签: java multithreading unit-testing spring-mvc eclipselink


【解决方案1】:

testGenerateWithThread() 需要 @Transactional 标签,因为您在 TestGenerateWithoutThread 上拥有它。请尝试以下操作:

@Test @Transactional public void TestGenerateWithThread() {

    final int loops = 5;

    final int threadCount = 1;

    final CyclicBarrier barrier = new CyclicBarrier(threadCount + 1);

    final boolean[] error = new boolean[] { false };

    Thread[] threads = new Thread[threadCount];
    for (int i = 0; i < threads.length; i++) {
        final int t = i;
        Runnable r = new Runnable() {
            @Override
            @Transactional
            public void run() {
                try {
                    barrier.await();
                } catch (InterruptedException e) {
                    error[0] = true;
                } catch (BrokenBarrierException e) {
                    error[0] = true;
                }
                for (int j = 0; j < loops; j++) {
                    String tagGenerate = productSequence.generate(prefix);
                    tags.add(tagGenerate);
                    System.out.println("In thread " + t + ": " + tagGenerate);
                }
            }
        };
        threads[i] = new Thread(r);
        threads[i].start();
    }

    try {
        barrier.await();
    } catch (InterruptedException e1) {
        System.out.println("Interrupted whilst waiting for barrier");
    } catch (BrokenBarrierException e1) {
        System.out.println("Broken barrier");
    }

    for (int i = 0; i < threads.length; i++) {
        try {
            threads[i].join();
        } catch (InterruptedException e) {
            System.out.println("Interrupted whilst joining thread " + i);
        }
    }

    assertEquals(threadCount * loops, tags.size());
}

【讨论】:

  • 感谢您的回复。但我尝试将它放在 testGenerateWithThread() 上但它不起作用。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2013-05-05
  • 2013-05-30
  • 1970-01-01
  • 1970-01-01
  • 2022-08-17
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多