我正在编写我的第一个单元测试(使用Mockito)。我想测试的功能结构如下:
class ClassA {
public ClassB b;
public void methodA() {
// calls a method of ClassB
b.methodB();
}
}
class ClassB {
public ClassC c;
public void methodB() {
// calls a method of ClassC
someVariable = c.methodC();
}
}
class ClassC {
public Object methodC() {
// do something
// this method needs to be mocked for testing (needs to return dummy values to ClassB)
}
}
我真正希望测试的是ClassB
中引入的某项功能是否仍然有效。为此,我需要methodC()
(从ClassB
调用)来返回某些值,因此我嘲笑ClassC
。
我的问题是,我遇到的所有教程都没有显示正在测试的类是从另一个类调用的(就像我的情况一样 - ClassB
从ClassA
调用)。
此外,教程显示被测试的类的实例被模拟,与我的情况不同(我正在测试ClassB
但需要模拟ClassC
)。
我应该如何为ClassB
编写单元测试?我对这个单元测试的看法如下:
@RunWith(MockitoJUnitRunner.class)
class TestB {
public ClassA instanceA;
public ClassB instanceB;
@Mock
public ClassC instanceC;
public void setUp() {
// do setup stuff
when(instanceC.methodC()).thenReturn(dummyValue);
b.setC(instanceC);
}
@Test
public void Test() {
}
}
我还没有尝试过这个,但我想知道这种方法是否合理,或者我的单元测试是否被错误地建模。谢谢!
答案 0 :(得分:1)
我的问题是,我遇到的所有教程都没有显示正在测试的课程是从另一个类调用的
你不应该担心。当您测试ClassB
时,您无需考虑其来电者。此时您唯一的目标是测试ClassB
的功能,而不是其他任何内容。
因此,您可以从public ClassA instanceA;
课程中删除TestB
。您的setUp
方法看起来不错。
以下是您的测试方法的外观
@Test
public void test_methodB() {
instanceB.methodB();
//Rest depends on the logic within methodB. Maybe use Mockito verify to verify certain calls were made, use Answers etc.
}
此外,教程显示了被测试的类的实例被模拟
我不明白为什么需要嘲笑被测系统。
答案 1 :(得分:0)
正如user7所提到的,你永远不应该模拟被测试的类。模拟应该用于模拟依赖类,这样你就不必创建依赖类(假设它在构造函数中需要3个参数,每个参数需要进一步的参数来构造它们;为了避免这种情况,我们用mock)。不是创建依赖类实例,而是模拟它,并设置预期行为(使用when(mockedObject.someMethod()).return(dummyValue)
)并仅测试您的类。如果依赖类的行为应该如此,我的类的行为是否符合我的预期?所以,你的setUp方法是正确的。您可以设置ClassC的期望值,然后测试ClassB。
答案 2 :(得分:0)
只需订购一下@ user7所说的更容易一点。
在ClassBTest中你应该模拟正在使用的classC的实例,并确保在instaceB.methodB()上调用methodC(与以前一样,同时查看InjectMocks注释)
@RunWith(MockitoJUnitRunner.class)
class TestB {
@InjectMocks
public ClassB instanceB;
@Mock
public ClassC instanceC;
public void setUp() {
// do setup stuff
when(instanceC.methodC()).thenReturn(dummyValue);
}
@Test
public void Test() {
instaceB.methodB();
}
}