Pergunta

Eu quero testar um pedaço de código que rede usa (a classe NSURLConnection, para ser mais específico). O código (vamos chamá-lo NetworkManager) parece um pouco com isto:

- (id) buildConnection
{
    // some more code and then:
    return [NSURLConnection …];
}

- (void) startNetworkSync
{
    id connection = [self buildConnection];
    //…
}

No teste de unidade que eu gostaria de se livrar da rede, ou seja. substituir o objecto NSURLConnection por uma falsa. Como posso fazer isso?

Eu tentei criar um mock parcial do NetworkManager que substituiria o método buildConnection por um topo. O problema é que as simulações parciais feitos por OCMock mensagens somente stub do mundo do lado de fora -. envio buildConnection do startNetworkSync invoca o método original, não o toco

Eu também tentei macaco-remendar a classe NetworkManager através de uma categoria. Isso funciona, eu posso facilmente substituir o método buildConnection por outro código e substituir o NSURLConnection real com um topo. O problema é que eu não encontrei nenhuma maneira simples que eu poderia obter a conexão arrancado no teste -. A conexão é uma parte privada da NetworkManager

Então eu poderia subclasse o NetworkManager, substituir o método buildConnection e adicionar uma variável de instância mais um assessor para a conexão criada. Este parece ser um monte de código, no entanto.

Como você resolveria isso? Eu estou procurando uma solução que mantém o design de classe NetworkManager limpo e não requer muita magia nem muito código no teste.

Foi útil?

Solução

Este é o tipo de injeção de dependência coisa é projetado para resolver; se você usar startNetworkSyncWithConnection:(NSURLConnection*) em vez disso você pode facilmente testar o método com uma conexão falsa. Se você não quiser alterar a API para os seus clientes que você ainda poderia manter startNetworkSync como um invólucro que não faz nada mas a chamada que o novo método com [self buildConnection] como argumento.

Outras dicas

Eu modifiquei OCMock para suportar simulações parciais reais, consulte o repo no GitHub .

Outra solução que tenho usado recentemente é completamente abstrato da interface de rede. Se a classe precisa de alguns dados da rede, ele provavelmente interage com algum serviço de servidor que pode ser explicitamente modelado como um protocolo:

@protocol SomeNetworkService
- (NSArray*) allAvailableFoos;
- (void) insertNewFoo: (Foo*) foo;
@end

E então você vai ter uma implementação HTTP real e um teste. Isso significa mais trabalho, mas também muito melhor testabilidade. Os testes são menos frágil e muito mais conveniente, uma vez que a camada de rede de testes pode fazer o que você precisa.

Licenciado em: CC-BY-SA com atribuição
Não afiliado a StackOverflow
scroll top