简体   繁体   English

使用 Guice,如何将单元测试中的模拟对象注入正在测试的类中

[英]Using Guice, how do I inject a mock object from my unit test, into the class being tested

Consider the following code:考虑以下代码:

@Singleton
public class MyServiceImpl {
    public int doSomething() {
        return 5;
    }
}

@ImplementedBy(MyServiceImpl.class)
public interface MyService {
    public int doSomething();
}

public class MyCommand {
    @Inject private MyService service;

    public boolean executeSomething() {
        return service.doSomething() > 0;
    }
}

public class MyCommandTest {
    @InjectMocks MyServiceImpl serviceMock;
    private MyCommand command;

    @Before public void beforeEach() {
        MockitoAnnotations.initMocks(this);
        command = new MyCommand();
        when(serviceMock.doSomething()).thenReturn(-1); // <- Error here
    }

    @Test public void mockInjected() {
        boolean result = command.executeSomething();
        verify(serviceMock).doSomething();
        assertThat(result, equalTo(false));
    }
}

My test is falling over when I attempt to stub the doSomething() method on my mock implementation object.当我尝试在模拟实现对象上存根 doSomething() 方法时,我的测试失败了。 I get the error:我收到错误:

org.mockito.exceptions.misusing.MissingMethodInvocationException: when() requires an argument which has to be 'a method call on a mock'. org.mockito.exceptions.misusing.MissingMethodInvocationException: when() 需要一个必须是“模拟方法调用”的参数。 For example: when(mock.getArticles()).thenReturn(articles);例如:when(mock.getArticles()).thenReturn(articles);

Also, this error might show up because: 1. you stub either of: final/private/equals()/hashCode() methods.此外,出现此错误的原因可能是: 1. 您存根了以下任一方法: final/private/equals()/hashCode() 方法。 Those methods cannot be stubbed/verified.这些方法不能被存根/验证。 Mocking methods declared on non-public parent classes is not supported.不支持在非公共父类上声明的模拟方法。 2. inside when() you don't call method on mock but on some other object. 2. 在 when() 中,您不会在模拟上调用方法,而是在其他对象上调用方法。

I am new to dependency injection via Guice, and am not sure why I cannot mock the implementation object in this way?我是通过 Guice 进行依赖注入的新手,不知道为什么我不能以这种方式模拟实现对象?

Test without CDI没有 CDI 的测试

A simple solution is to combine CDI with Constructor Injection, and forget about Guice for the test:一个简单的解决方案是将 CDI 与构造函数注入结合起来,而无需考虑 Guice 进行测试:

public class MyCommand {
    private final MyService service;

    @Inject
    public MyCommand(MyService service) {
        this.service = service;
    }

    public boolean executeSomething() {
        return service.doSomething() > 0;
    }
}

@RunWith(MockitoJUnitRunner.class)
public class MyCommandTest {
    @Mock
    MyServiceImpl serviceMock;
    private MyCommand command;

    @Before public void beforeEach() {
        MockitoAnnotations.initMocks(this);
        when(serviceMock.doSomething()).thenReturn(-1); // <- Error here

        // inject without Guice
        command = new MyCommand(serviceMock);
    }
}

Test with Mockito doing CDI用 Mockito 做 CDI 测试

Else, if you do not like Constructor Injection, the test code should look like this:否则,如果您不喜欢构造函数注入,则测试代码应如下所示:

@RunWith(MockitoJUnitRunner.class)
public class MyCommandTest {
    @Mock
    MyServiceImpl serviceMock;
    @InjectMocks 
    private MyCommand command;

    @Before 
    public void beforeEach() {
        MockitoAnnotations.initMocks(this);
        command = new MyCommand();
        when(serviceMock.doSomething()).thenReturn(-1); // <- Error here
    }
}

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM