Em uma bela sexta feira, você parou e pensou
Mas pra que caralho eu uso mock?
Tá, pode ser que você tenha pensado isso ou não. Antes de respondermos isso precisamos entender como podemos escrever um teste para um componente A sem depender de suas dependências.
Antes de entendermos o problema anterior, por que gostaríamos de fazer isso? Para que não tenhamos de lidar com a complexidade que as dependências irão exercer no SUT!
Para isso nós teríamos de criar um objeto que seja capaz de imitar o comportamento de B. Dessa forma, teríamos o controle completo do componente B dado o contexto do testes sem ter a necessidade de lidarmos a dependência concreta.
Benefícios
A capacidade de usar um objeto que se comporta como outro objeto nos traz:
- Maior controle da dependência dado o cenário de teste;
- Melhoria no tempo de feedback;
- Reflexão de como as classes interagem entre si.
Imitando objetos
Bom, até agora entendemos o benefício de removermos a dependência concreta e adicionarmos um objeto que a imita. Esses mímicos possuem nomes específicos dado o comportamento que realizam.
Fake
São objetos que possuem uma implementação concreta porém mais simples do objeto sendo imitado.
Dummies
São objetos que são utilizados apenas para preencher um parâmetro.
Stubs
São objetos que fornecem retornos previamente definidos às chamadas realizadas durante o teste, permitindo que tenhamos o controle do comportamento da dependência durante o teste.
Spies
São objetos similares ao Stub
, mas, além de fornecer respostas previamente definidas, ele também registra informações sobre as interações feitas com eles.
Mocks
São objetos simulados que verificam se certas interações foram realizadas. Sua configuração é feita a partir de expectativas sobre como os métodos devem ser chamados e com quais parâmetros.
Exemplos
Agora que conhecemos o que são Test doubles
iremos vê-los na prática, para isso tomemos um exemplo do nosso cotidiano um DataSouce
abstract class RemoteDataSource {
Future<Response> fetch(String url);
}
Dummies
class DummyDataSource implements DataSource {
@override
Future<Response> fetchData(String url) async {
return Response(
requestOptions: RequestOptions(path: url),
);
}
}
Fake
class FakeDataSource implements DataSource {
final Map<String, dynamic> fakeResponses;
FakeDataSource(this.fakeResponses);
@override
Future<Response> fetch(String url) async {
await Future.delayed(Duration(milliseconds: 100));
if (fakeResponses.containsKey(url)) {
return Response(
data: fakeResponses[url],
requestOptions: RequestOptions(path: url),
);
} else {
return Response(
statusCode: 404,
statusMessage: 'Not Found',
requestOptions: RequestOptions(path: url),
);
}
}
}
Stub
class StubDataSource implements DataSource {
@override
Future<Response> fetch(String url) async {
await Future.delayed(Duration(milliseconds: 50));
if (url.contains('/item1')) {
return Response(
data: {'name': 'Item 1', 'price': 10.0},
requestOptions: RequestOptions(path: url),
);
} else if (url.contains('/item2')) {
return Response(
data: {'name': 'Item 2', 'price': 20.0},
requestOptions: RequestOptions(path: url),
);
} else {
return Response(
statusCode: 500,
statusMessage: 'Internal Server Error',
requestOptions: RequestOptions(path: url),
);
}
}
}
Spy
class SpyDataSource implements DataSource {
int fetchCalls = 0;
@override
Future<Response> fetch() async {
fetchCalls++;
return Response(
data: {'key': 'spyValue'},
requestOptions: RequestOptions(path: '/spy'),
);
}
}
Mock
class MockDataSource extends Mock implements DataSource {}
test('fetch should be called and return mocked value', () async {
final mockDataSource = MockDataSource();
when(() => mockDataSource.fetch()).thenAnswer(
(_) async => Response(
data: {'key': 'mockedValue'},
requestOptions: RequestOptions(path: '/mock'),
),
);
final response = await mockDataSource.fetch();
expect(response.data, {'key': 'mockedValue'});
verify(() => mockDataSource.fetch()).called(1);
});
}
Bibliografia
- Fowler. Martin, “Testing Double.” martinfowler.com. Acessado em 1 de agosto de 2024.
- Aniche. Mauricio, “Effective Software Testing: A Developer’s Guide”, Manning Publications.