描述:我已经测试了methodA()
和methodB()
,所以我可以确保它们被覆盖。通过模拟同一文件中的methodA()
和methodB()
来测试methodToBeTested()
的方法有哪些?参数通过methodToBeTested()
传递到methodA()
和methodB()
,以使用注入正确地测试这些方法。注意:它们不能被提取到不同的类,因为它是计算服务的相关逻辑,并且这些方法已经被原子分离。
代码:
class ClassForTesting {
int methodToBeTested(String a, String b) {
// Calculation in this method also is a bit more difficult
return methodA() + methodB();
}
int methodA(String a) {
int value = 1;
// Here is calculation logic that has been tested
return value;
}
int methodB(String b) {
int value = 2;
// Here is calculation logic that has been tested
return value;
}
}
已经做了什么:我尝试了Mockito的几种方法,但它不允许这样做:
@GenerateMocks
-正在创建一个mock,并要求我使用when()
,甚至methodToBeTested()
来存根每个方法- 通过使用下一个构造扩展Fake:
class Mock extends Fake implements PasswordValidatorService {}
但通过这种方式,我只继承了PasswordValidatorService's
行为,而不是实现,并且每个未重写的方法都抛出UnimplementedError
。因此,我无法覆盖methodToBeTested()
并调用它的超级实现。
我发现Mockito for Java具有@Spy
构造,在这种情况下这将是完美的,但不幸的是,它不适用于Dart和Flutter。
我目前唯一的方法是创建我自己的Mock:
class MockClassForTesting extends ClassForTesting {
@override
int methodA() {
return 2;
}
@override
int methodB() {
return 5;
}
}
但是这个实现不允许我使用Mockito对when()
构造的灵活性,因为我必须有不同的methodA()
和methodB()
返回。这一事实迫使我在MockClassForTesting
中有额外的变量来实现when()
构造功能。
问题:
- 实现我的目的的最佳方式是什么
- 在Widget测试期间可以使用相同的嘲讽方法吗
一种方法是使用混合方法,在该方法中创建自己的派生类,但其中一些重写委托给Mock
实现。例如:
class ClassForTesting {
int methodToBeTested(String a, String b) {
// Calculation in this method also is a bit more difficult
return methodA(a) + methodB(b);
}
int methodA(String a) {
int value = 1;
// Here is calculation logic that has been tested
return value;
}
int methodB(String b) {
int value = 2;
// Here is calculation logic that has been tested
return value;
}
}
class PartialMockClassForTesting extends ClassForTesting {
final mock = MockClassForTesting();
@override
int methodA(String a) => mock.methodA(a);
@override
int methodB(String b) => mock.methodB(b);
}
@GenerateMocks([ClassForTesting])
void main() {
test('Test partial mock', () {
var partialMock = PartialMockClassForTesting();
when(partialMock.methodA('hello')).thenReturn(42);
when(partialMock.methodA('goodbye')).thenReturn(-42);
when(partialMock.methodB('world')).thenReturn(10);
expect(partialMock.methodToBeTested('hello', 'world'), 52);
expect(partialMock.methodToBeTested('goodbye', 'world'), -32);
});
}
如果您想有条件地模拟某些方法,可以让您的重写检查布尔标志来有条件地调用mock或实际实现。例如:
class PartialMockClassForTesting extends ClassForTesting {
final mock = MockClassForTesting();
final shouldMock = <Function, bool>{};
@override
int methodA(String a) =>
shouldMock[methodA] ?? false ? mock.methodA(a) : super.methodA(a);
@override
int methodB(String b) =>
shouldMock[methodB] ?? false ? mock.methodB(b) : super.methodB(b);
}
@GenerateMocks([ClassForTesting])
void main() {
test('Test partial mock', () {
var partialMock = PartialMockClassForTesting();
partialMock.shouldMock[partialMock.methodA] = true;
partialMock.shouldMock[partialMock.methodB] = true;
...