开发者

Need reassurance on Unit Tests and best practices

I have not been doing TDD and Unit Tests for 7 months now and I kind of forgot. I am now in shop that wants to start doing it but I am the only one there and not exactly a guru in the matter.

I am a bit rusty and I am getting all sorts of questions and many times I cannot give a proper answer.

Typical questions I get:

  • I dont see anything wrong with integration Testing? I told them is slow ,you should never do it.

    If I cannot test privateMethod (I know MSTest does) what is the point in testing? All my important methods are private.

    I dont see the point of setting up an expectation and return a result that pleases the test?

    What are the typical unit tests you should perform in each layer? Should you test only at boundary levels?

    How do I test my Stored Procedure return the intended results?

Do you think the below tests make any sense to you?What kind of test would you generally do at each layer?Any examples with code?

I do 3 kinds of tests

1)ViewModel Tests.

2)Wcf Tests by mocking the service

3)Wcf Integratontest but mocking开发者_运维知识库 the Dal

Is this what you do?.Can you correct me if yoou thing this is wrong.Can you improve them?

ViewModel tests property has changed and methods have been called example below

      //property has changed
      [TestMethod]
      public void Should_be_able_to_test_that_customer_description_propertyChanged_was_raised()
      {
         //act
         var customerResponse=new CustomerResponse{Description = "Test"};
         var customerViewModel = new CustomerViewModel(customerResponse);
         var eventWasRaised = false;

         customerViewModel.PropertyChanged += (sender, e) => eventWasRaised = e.PropertyName == "Description";
         customerViewModel.Description = "DescriptionTest";


         Assert.IsTrue(eventWasRaised, "PropertyChanged event was not raised correctly.");
      }

        //Testing a method on the view model has been called
        [Test]
        public void Should_be_able_to_test_that_insert_method_on_view_Model_has_been_executed()
        {
            var mock = new Mock<IRepository>();
            var employeeVm = new EmployeeVM(mock.Object) {Age = 19};
            employeeVm.SaveCommand.Execute(null);
            mock.Verify(e=>e.Insert(It.IsAny<Employee>()));
        }

WCF Unit Tests

// Test 1 mocking the service

      [TestMethod]
      public void Should_be_able_to_verify_getCustomer_has_been_called)
      {
         var mockService = new Mock<ICustomer>();
         var expectedCustomer=new Customer{Id=1,Name="Jo"};
         mockService.Setup(x => x.GetCustomer(It.IsAny<int>())).Returns(expectedCustomer);

         var customerViewModel = new customerViewModel(mockService.Object);
         customerViewModel.GetCustomer.Execute(null);

         mockService.Verify(x=>x.GetCustomer(),Times.AtLeastOnce());
      }

      //Test 2 mocking the repository
      [TestMethod]
      public void Should_be_able_to_verify_getCustomer_has_been_called_on_the_service)
      {
         var mockRepository = new Mock<IRepositoryCustomer>();
         var expectedCustomer=new Customer{Id=1,Name="Jo"};
         mockRepository.Setup(x => x.GetCustomer(It.IsAny<int>())).Returns(expectedCustomer);

         var customerService = new CustomerService(mock.Object);
         customerService.GetCustomer(1);

         mockRepository.Verify(x=>x.GetCustomer(),Times.AtLeastOnce());
      }


Ok let's see if I can answer

I dont see anything wrong with integration Testing? I told them is

slow ,you should never do it.

Integration tests is an overloaded term now. When you're writing unit tests, you want to substitute fakes/mocks for timeconsuming/unpredictable/expensive real collaborators so that you can focus on your own code (and assume that the real collabs satisfy an assumed contract). This can help you run your unit tests in a fraction of the time leading to faster feedback and progress. Also a test failure now indicates an error in your code.. the converse being any error in any dependency can cause your test to fail

You also need other (slow) tests that verify if the real collabs (e.g. the DAL) behave as per the contract. (I tend to call these integration tests now)

If I cannot test privateMethod (I know MSTest does) what is the point in testing? All my important methods are private.

Private methods should be tested via the public interface which exercises them. Write tests for the public methods which call the private methods.. If this cannot be done, maybe the private methods or parts of it are redundant.

I dont see the point of setting up an expectation and return a result that pleases the test?

See answer#1- you're assuming that the real dependencies will behave as per an agreed contract. This allows you to focus on the code you're writing using the dependencies.

What are the typical unit tests you should perform in each layer? Should you test only at boundary levels?

Unit tests should test objects, Acceptance tests verify that all the objects work together when plugged into each other

How do I test my Stored Procedure return the intended results?

Write a test that exercises the DAL against a known reference database and verify the expected results. This should be tagged as a slow integration test (as per my chosen definition).


The tests you've written are a pretty good start! Trying it out, practicing and working out what works and what doesn't is how anyone who is a 'guru' becomes one in the first place. (I've not met any 'gurus' yet; just people with years of practice).

There are a few questions so I'm going to answer them in turn.

Integration Testing is really slow, yes.

I normally do this for the whole application, from the Gui or web page, for certain key scenarios across the entire system, because performing the same tests manually is time consuming. As the application grows, so does the amount of regression testing which the testers will have to do. You can help them by writing these automated tests.

Developers hardly ever see the benefit of the automated tests, because it's the testers who really need them and use them. Think of it from their perspective and you may see more value.

Actually deriving the scenarios in the first place can be valuable because it helps developers, testers and analysts find and address differences in their understanding of the system.

Testing private methods should be unnecessary. However...

If your method is complex, you can always split it out into a different class, and make your class collaborate with that one. If your private methods are the important ones then you probably should do this.

Also, don't test methods. Describe each aspect of the behaviour of your class, show why it's valuable and give some examples of using it. Behaviour may involve more than one method. For instance, list.isEmpty requires us to work with list.add too; it's the interaction between them which is important for things using list.

This is also why we don't test private methods - because they're of no benefit to the class using them on their own.

The names of your tests could help to reflect this. Think "My view model should..." and then consider how it provides the valuable behaviour which it does. For instance, I would phrase your first test as "My View Model should notify listeners that the description changed", so ShouldNotifyListenersThatTheDescriptionChanged.

Instead of setting up an expectation, consider that your class has some collaborating classes.

Some of them provide the class with information - contexts which change its behaviour, producing different outcomes. Some of them do jobs for the class. The first are "stubs", the second "mocks" (terminology here is mixed across the business).

Rather than setting up expectations, you're providing an example which shows how the class behaves within that context.

Rather than verifying an outcome, you're showing that the class delegates its responsibilities appropriately.

Mocks are just a useful way to do that.

The typical tests I write are those which help me describe the behaviour of the code, ensure its responsibilities are appropriate and show why the code is valuable. That's most of the code, but I won't write examples for trivial classes - for instance, custom exceptions, objects which are just data or properties, etc.

You can show the behaviour of a stored procedure by writing examples of using it in the different contexts which show the different aspects of behaviour. You may need to set up some data for this to work. Most teams I work with avoid stored procedures just because of the difficulty of testing them, or they simply rely on the full-stack scenarios to provide coverage.

Hope this helps, and best of luck!

0

上一篇:

下一篇:

精彩评论

暂无评论...
验证码 换一张
取 消

最新问答

问答排行榜