Mockbean mockito在新线程中不起作用。

huangapple go评论107阅读模式
英文:

Why Mockbean mockito not work in new thread

问题

我发现Mockbean在测试主线程中起作用,但在新线程调用时不起作用,以下是我的演示代码。第一次在新线程中调用模拟是有效的,但在第二次调用demoService时,它返回null(模拟不起作用)。

参考Jar版本
mockito-core 4.11.0
JDK1.8
Junit4
SpringBoot: 1.5.22.RELEASE

英文:

I found that Mockbean is work the test main thread, but not work in the new thread call, following is my demo code. call the mock first time in new thread is work, but when call the demoService in second times, it return null (mock not work)

##Reference Jar Version
mockito-core 4.11.0
JDK1.8
Junit4
SpringBoot: 1.5.22.RELEASE

/***
 * demo test case for find why mockito mock not work in new thread
 */
@RunWith(SpringJUnit4ClassRunner.class)
@SpringBootTest(classes = DemoApplication.class)
public class DemoApplicationTests {

	@MockBean
	protected DemoService demoService;


	/**
	 * call the mock in main thread, the mock all work
	 */
	@Test
	public void testNormalCase_work() {

		DemoServiceMock.mockdoSomething(demoService);

		String result = demoService.doSomething("324234");
		System.out.println("return: " + result);

		String result2 = demoService.doSomething("324234");
		System.out.println("return2: " + result);
	}


	/***
	 * call the mock in new thread
	 * When call the demoService in second times, it return null (mock not work)
	 */
	@Test
	public void testInNewThread_notWork() {

		DemoServiceMock.mockdoSomething(demoService);


		Thread t = new Thread(new Runnable() {
			public void run() {
				//for the first time call, the mock is work
				String result = demoService.doSomething("324234");
				System.out.println("return in thread: " + result);

				//for this second time call in new thread, the mock not work and return null
				String result2 = demoService.doSomething("324234");
				System.out.println("return2 in thread: " + result2);

			}
		});

		t.start();

	}


}

public class DemoServiceMock {

    public static void mockdoSomething(DemoService demoService){

        Mockito.doReturn("mockReturnValue").when(demoService).doSomething(any());

    }
}

I found that Mockbean is work the test main thread, but not work in the new thread call, following is my demo code. call the mock first time in new thread is work, but when call the demoService in second times, it return null (mock not work)

##Reference Jar Version
mockito-core 4.11.0
JDK1.8
Junit4
SpringBoot: 1.5.22.RELEASE

答案1

得分: 0

无法在本地重现您的行为(尽管使用JUnit 5、Spring Boot 2和JDK 11)。然而,您没有等待线程完成的行为非常可疑。多次运行测试可能会成功或失败,这取决于执行语句的顺序。

第二次调用可能是在测试运行程序已关闭并取消注册任何存根调用的情况下进行的。这是一个典型的竞态条件的示例。

等待线程完成可能会“解决”您的问题:

@Test
public void testInNewThread_notWork() {
    DemoServiceMock.mockdoSomething(demoService);

    Thread t = new Thread(new Runnable() {
        public void run() {
            //第一次调用时,模拟有效
            String result = demoService.doSomething("324234");
            System.out.println("return in thread: " + result);

            //在新线程中进行的第二次调用,模拟无效并返回null
            String result2 = demoService.doSomething("324234");
            System.out.println("return2 in thread: " + result2);

        }
    });

    t.start();
    t.join(); //等待线程完成执行!
}

另外,请自己考虑停止使用过时/生命周期结束的软件和库。现在已经有JUnit 5、Spring Boot 3和JDK 17。后者仍然会获得更新和安全修复,而您的版本则保持不维护和容易受到攻击。

英文:

I cannot reproduce your behavior locally (with JUnit 5, Spring Boot 2, and JDK 11 though).
Nevertheless, it is very fishy that you do not wait for your thread to complete. Running the test multiple times could succeed or fail, depending on the order of execution of your statements.

By the time the second call is made, the test runner has probably shut down and deregistered any stubbing calls. A prime example of a race condition

Waiting for the thread to complete would likely "solve" your problem:

@Test
public void testInNewThread_notWork() {
    DemoServiceMock.mockdoSomething(demoService);

    Thread t = new Thread(new Runnable() {
        public void run() {
            //for the first time call, the mock is work
            String result = demoService.doSomething("324234");
            System.out.println("return in thread: " + result);

            //for this second time call in new thread, the mock not work and return null
            String result2 = demoService.doSomething("324234");
            System.out.println("return2 in thread: " + result2);

        }
    });

    t.start();
    t.join(); // wait for thread to complete execution!
}

PS do yourself a favor and stop using obsolete/end-of-life software and library. There's JUnit 5, Spring Boot 3, and JDK 17. All of the latter still get updates and security fixes, while your versions remain unmaintained and vulnerable.

huangapple
  • 本文由 发表于 2023年8月10日 11:29:58
  • 转载请务必保留本文链接:https://go.coder-hub.com/76872486.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定