Sua pergunta era sobre como o framework do MS Fakes é diferente do NMock e parece que as outras respostas resolveram parte disso, mas aqui estão mais algumas informações sobre como eles são iguais e como são diferentes. NMock também é semelhante a RhinoMocks e Moq, então estou agrupando-os com NMock.
Existem 3 diferenças principais que vejo imediatamente entre NMock / RhinoMocks / Moq e o MS Fakes Framework:
A estrutura do MS fakes usa código gerado, bem como Accessors em versões anteriores do Visual Studio, em vez de tipos genéricos. Quando você deseja usar a estrutura fakes para uma dependência, você adiciona o assembly que contém a dependência às referências do projeto de teste e, em seguida, clica com o botão direito nele para gerar os dublês de teste (stubs ou shims). Então, quando você está testando, na verdade está usando essas classes geradas. NMock usa genéricos para realizar a mesma coisa (ou seja IStudentRepository studentRepository = mocks.NewMock<IStudentRepository>()
). Na minha opinião, a abordagem do framework MS Fakes inibe a navegação e refatoração de código de dentro dos testes, já que você está realmente trabalhando em uma classe gerada, não em sua interface real.
A estrutura do MS fakes fornece stubs e moles (shims), enquanto NMock, RhinoMocks e Moq fornecem stubs e mocks . Eu realmente não entendo a decisão da MS de não incluir mocks e eu, pessoalmente, não sou um fã de toupeiras pelos motivos descritos abaixo.
Com a estrutura MS fakes, você fornece uma implementação alternativa dos métodos que deseja criar stub. Dentro dessas implementações alternativas, você pode especificar os valores de retorno e rastrear informações sobre como ou se o método foi chamado. Com NMock, RhinoMocks e Moq, você gera um objeto simulado e usa esse objeto para especificar valores de retorno fragmentados ou para rastrear interações (se e como os métodos foram chamados). Acho a abordagem das falsificações do MS mais complexa e menos expressiva.
Para esclarecer a diferença no que as estruturas fornecem: NMock, RhinoMocks e Moq fornecem dois tipos de duplas de teste (stubs e mocks). A estrutura do fakes fornece stubs e moles (eles os chamam de shims) e, infelizmente, não inclui mocks. Para entender as diferenças e semelhanças entre NMock e MS Fakes, é útil entender quais são esses tipos diferentes de duplas de teste:
Stubs: Stubs são usados quando você precisa fornecer valores para métodos ou propriedades que serão solicitados a seus dublês de teste pelo método em teste. Por exemplo, quando meu método em teste chama o método DoesStudentExist () do teste duplo IStudentRepository, eu quero que ele retorne verdadeiro.
A ideia de stubs em fakes de NMock e MS é a mesma, mas com NMock você faria algo assim:
Stub.On(mockStudentRepository).Method("DoesStudentExist").Will(Return.Value(true));
E com o MSFakes você faria algo assim:
IStudentRepository studentRepository = new DataAccess.Fakes.StubIStudentRepository() // Generated by Fakes.
{
DoesStudentExistInt32 = (studentId) => { return new Student(); }
};
Observe que no exemplo do MS Fakes você cria uma implementação inteiramente nova para o método DoesStudentExist (Observe que é chamado DoesStudentExistInt32 porque a estrutura fakes anexa os tipos de dados do parâmetro aos nomes dos métodos quando gera os objetos stub, acho que isso obscurece a clareza de Os testes). Para ser honesto, a implementação de NMock também me incomoda porque usa uma string para identificar o nome do método. (Perdoe-me se não entendi como o NMock deve ser usado.) Essa abordagem realmente inibe a refatoração e eu recomendo fortemente o RhinoMocks ou o Moq em vez do NMock por esse motivo.
Mocks: Mocks são usados para verificar a interação entre o método em teste e suas dependências. Com NMock, você faz isso definindo expectativas semelhantes a esta:
Expect.Once.On(mockStudentRepository).Method("Find").With(123);
Esta é outra razão pela qual eu prefiro RhinoMocks e Moq ao invés de NMock, NMock usa o estilo de expectativa mais antigo, enquanto RhinoMocks e Moq suportam a abordagem Arrange / Act / Assert onde você especifica as interações esperadas como asserções no final do teste como este :
stubStudentRepository.AssertWasCalled( x => x.Find(123));
Novamente, observe que RhinoMocks usa um lambda em vez de uma string para identificar o método. A estrutura do ms fakes não fornece simulações. Isso significa que em suas implementações esboçadas (consulte a descrição de esboços acima), você deve definir variáveis que, posteriormente, verificar se foram definidas corretamente. Seria mais ou menos assim:
bool wasFindCalled = false;
IStudentRepository studentRepository = new DataAccess.Fakes.StubIStudentRepository()
{
DoesStudentExistInt32 = (studentId) =>
{
wasFindCalled = true;
return new Student();
}
};
classUnderTest.MethodUnderTest();
Assert.IsTrue(wasFindCalled);
Acho que essa abordagem é um pouco complicada, já que você precisa rastrear a chamada no esboço e, em seguida, confirmá-la mais tarde no teste. Acho o NMock, e especialmente o RhinoMocks, exemplos mais expressivos.
Moles (Shims): Para ser franco, eu não gosto de verrugas, por causa de seu potencial para uso indevido. Uma das coisas que eu gosto tanto no teste de unidade (e TDD em particular) é que testar seu código o ajuda a entender onde você escreveu um código ruim. Isso ocorre porque testar códigos mal escritos é difícil. Isso não é verdade ao usar moles porque os moles são, na verdade, projetados para permitir que você teste dependências que não são injetadas ou para testar métodos privados. Eles funcionam de forma semelhante aos stubs, exceto que você usa um ShimsContext como este:
using (ShimsContext.Create())
{
System.Fakes.ShimDateTime.NowGet = () => { return new DateTime(fixedYear, 1, 1); };
}
Minha preocupação com os shims é que as pessoas começarão a vê-los como "uma maneira mais fácil de testar a unidade", porque não o força a escrever o código da maneira que deveria. Para um artigo mais completo sobre este conceito, veja este meu post:
Para obter mais informações sobre algumas questões relacionadas aos frameworks falsos, dê uma olhada nestes posts:
Se você estiver interessado em aprender o RhinoMocks, aqui está um vídeo de treinamento Pluralsight (divulgação completa - escrevi este curso e recebo royalties pelas visualizações, mas acho que se aplica a esta discussão, então estou incluindo aqui):