如何测试方法并模拟 Flutter 中相同 class 中的另一个方法
How can I test a method and to mock another method that are in the same class in Flutter
描述:
我已经测试了 methodA()
和 methodB()
,所以我可以确定它们都被覆盖了。
通过模拟同一文件中的 methodA()
和 methodB()
来测试 methodToBeTested()
的方法有哪些?参数通过 methodToBeTested()
传递给 methodA()
和 methodB()
以使用注入正确测试这些方法。
注意:它们不能被提取到不同的class,因为它是计算服务的相关逻辑,并且这些方法已经原子地分离了。
代码:
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
- 正在创建模拟并要求我使用 when()
存根每个方法,甚至 methodToBeTested()
.
- 通过使用下一个构造扩展 Fake:
class Mock extends Fake implements PasswordValidatorService {}
但通过这种方式,我只是继承了 PasswordValidatorService's
行为而不是实现,并且每个未覆盖的方法都会抛出 UnimplementedError
。因此,我无法覆盖 methodToBeTested()
并调用它的超级实现。
我发现 Java 的 Mockito 具有 @Spy
结构,在这种情况下是完美的,但不幸的是它不适用于 Dart 和 Flutter。
我目前唯一的方法是创建自己的 Mock:
class MockClassForTesting extends ClassForTesting {
@override
int methodA() {
return 2;
}
@override
int methodB() {
return 5;
}
}
但是这个实现不允许我使用 Mockito 的 when()
构造的灵活性,因为我必须有不同的 methodA()
和 methodB()
returns。
这个事实迫使我在我的 MockClassForTesting
中添加额外的变量来实现 when()
构造功能。
题目:
- 实现我的目标的最佳方法是什么?
- 可以在 Widget 测试期间使用相同的模拟方法吗?
谢谢!
一种方法是使用混合方法,您可以在其中创建自己的派生 class,但其中一些覆盖委托给 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);
});
}
如果您想有条件地模拟某些方法,您可以让您的覆盖检查布尔标志以有条件地调用模拟或实际实现。例如:
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;
...
描述:
我已经测试了 methodA()
和 methodB()
,所以我可以确定它们都被覆盖了。
通过模拟同一文件中的 methodA()
和 methodB()
来测试 methodToBeTested()
的方法有哪些?参数通过 methodToBeTested()
传递给 methodA()
和 methodB()
以使用注入正确测试这些方法。
注意:它们不能被提取到不同的class,因为它是计算服务的相关逻辑,并且这些方法已经原子地分离了。
代码:
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
- 正在创建模拟并要求我使用when()
存根每个方法,甚至methodToBeTested()
.- 通过使用下一个构造扩展 Fake:
class Mock extends Fake implements PasswordValidatorService {}
但通过这种方式,我只是继承了 PasswordValidatorService's
行为而不是实现,并且每个未覆盖的方法都会抛出 UnimplementedError
。因此,我无法覆盖 methodToBeTested()
并调用它的超级实现。
我发现 Java 的 Mockito 具有 @Spy
结构,在这种情况下是完美的,但不幸的是它不适用于 Dart 和 Flutter。
我目前唯一的方法是创建自己的 Mock:
class MockClassForTesting extends ClassForTesting {
@override
int methodA() {
return 2;
}
@override
int methodB() {
return 5;
}
}
但是这个实现不允许我使用 Mockito 的 when()
构造的灵活性,因为我必须有不同的 methodA()
和 methodB()
returns。
这个事实迫使我在我的 MockClassForTesting
中添加额外的变量来实现 when()
构造功能。
题目:
- 实现我的目标的最佳方法是什么?
- 可以在 Widget 测试期间使用相同的模拟方法吗?
谢谢!
一种方法是使用混合方法,您可以在其中创建自己的派生 class,但其中一些覆盖委托给 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);
});
}
如果您想有条件地模拟某些方法,您可以让您的覆盖检查布尔标志以有条件地调用模拟或实际实现。例如:
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;
...