Como zombar corretamente e teste de unidade

Estou basicamente tentando me ensinar a codificar e quero seguir boas práticas. Existem benefícios óbvios para o teste de unidade. Também há muito fanatismo quando se trata de testes unitários e prefiro uma abordagem muito mais pragmática à codificação e à vida em geral. Como contexto, atualmente estou escrevendo meu primeiro aplicativo "real", que é o onipresente mecanismo de blog usando o asp.net MVC. Estou seguindo vagamente a arquitetura MVC Storefront com meus próprios ajustes. Como tal, esta é minha primeira incursão real em objetos zombadores. Vou colocar o exemplo de código no final da pergunta.

Eu apreciaria qualquer insight ou recursos externos que eu pudesse usar para aumentar minha compreensão dos fundamentos de testes e zombarias. Os recursos que encontrei na rede geralmente são voltados para o "como" da zombaria e preciso de mais compreensão sobre onde, por que e quando zombar. Se este não é o melhor lugar para fazer essa pergunta, indique-me um lugar melhor.

Estou tentando entender o valor que estou obtendo dos seguintes testes. O UserService depende do IUserRepository. O valor da camada de serviço é separar sua lógica do armazenamento de dados, mas nesse caso a maioria das chamadas de UserService é passada diretamente para IUserRepository. O fato de não haver muita lógica real para testar também pode ser a fonte das minhas preocupações. Eu tenho as seguintes preocupações.

Parece que o código está apenas testando se a estrutura de simulação está funcionando.Para zombar das dependências, meus testes têm muito conhecimento da implementação do IUserRepository. Isso é um mal necessário?Que valor estou realmente ganhando com esses testes? A simplicidade do serviço em teste está me fazendo duvidar do valor desses testes.

Estou usando o NUnit e o Rhino.Mocks, mas deve ser bastante óbvio o que estou tentando realizar.

    [SetUp]
    public void Setup()
    {
        userRepo = MockRepository.GenerateMock<IUserRepository>();
        userSvc = new UserService(userRepo);
        theUser = new User
        {
            ID = null,
            UserName = "http://joe.myopenid.com",
            EmailAddress = "[email protected]",
            DisplayName = "Joe Blow",
            Website = "http://joeblow.com"
        };
    }

    [Test]
    public void UserService_can_create_a_new_user()
    {
        // Arrange
        userRepo.Expect(repo => repo.CreateUser(theUser)).Return(true);

        // Act
        bool result = userSvc.CreateUser(theUser);

        // Assert
        userRepo.VerifyAllExpectations();
        Assert.That(result, Is.True, 
          "UserService.CreateUser(user) failed when it should have succeeded");
    }

    [Test]
    public void UserService_can_not_create_an_existing_user()
    {
        // Arrange
        userRepo.Stub(repo => repo.IsExistingUser(theUser)).Return(true);
        userRepo.Expect(repo => repo.CreateUser(theUser)).Return(false);
        // Act
        bool result = userSvc.CreateUser(theUser);

        // Assert
        userRepo.VerifyAllExpectations();
        Assert.That(result, Is.False, 
            "UserService.CreateUser() allowed multiple copies of same user to be created");
    }

questionAnswers(4)

yourAnswerToTheQuestion