3

Just started learning and writing unit testing a day ago so this is probably too simple question:

I have this method in my DBTaskHanlder class that I want to do some unit for, I was able to write one for when ModelState is not valid but now for next one:

public bool CreateTask(ForgotPasswordViewModel fpModel)
{
    if (!ModelState.IsValid)
    {
        return false;
    }

    try
    {
         CreateTaskFromModel(fpModel);
        _dbContext.SaveChanges();
        return true;
    }
    catch (Exception e)
    {
        var issue = e.ToString();
        throw;
    }
}

That CreateTaskFromModel is a private method and well called its job is to create a new row in database on a table. So I wanted to test when this method is called is one new row getting created in DB? Is it actually the correct thing to test? How to test ? I don't think we should hit and insert into the real database right?

   private void CreateTaskFromModel(ForgotPasswordViewModel fpModel)
    {
        var message = _dbContext.Create<Message>();          
        message.MessageType = "TASK".PadLeft(10);
        message.Assigned_User_K = fpModel.SendPasswordRequestTo.Trim();
        message.Assigned_Date = DateTime.Today;
        message.Source_User_K = string.Empty;
        message.Target_File_K = "WEBCFGPHRM";           
        message.Owner_User_K = string.Empty;
        message.Message_K = _keyGenerator.Get10ByteBase36Key();

        _dbContext.Messages.Add(message);
    }
Joe
  • 46,419
  • 33
  • 155
  • 245
  • 5
    It is correct thing to test, but it should not be called "unit test" at that point - "integration test" would be better name. See http://stackoverflow.com/questions/10752/what-is-the-difference-between-integration-and-unit-tests – Alexei Levenkov Jun 16 '16 at 16:33

2 Answers2

5

I don't think we should hit and insert into the real database right?

Yes you should. It isn't a "unit test", but it is a valuable test. As you get better at programming, you'll find that most of your bugs are at the edges of your program where it touches other things like databases.

I like writing CRUD tests. One "test method" that actually performs a series of tests. Usually in this pattern:

  1. Create
  2. Read by primary key. Were all the fields properly set?
  3. Read by a collection. You'll get lots of records, is the newly created record in the collection?
  4. Update
  5. Read by primary key. Did the fields change correctly?
  6. Delete
  7. Read by primary key. Nothing was returned, right?
  8. Read by a collection. You'll get lots of records, is the newly created record no longer in the collection? Are the rest of the records still there?

Even though everything is in one big method, treat each step as its own test that happens to use the previous test as a setup.

Jonathan Allen
  • 68,373
  • 70
  • 259
  • 447
  • yes I don't want to kinda do integration test on that, somebody else in the past has written the actual insert code stuff so I am just doing a pure unit test –  Jun 16 '16 at 17:25
  • The class is called `DBTaskHandler`. That's a pretty good sign that you should be testing it in conjunction with a database. Don't allow yourself to get lured into thinking that unit tests are somehow better than integration tests. Despite what the bloggers say, no test is inherently better than another in a global sense. – Jonathan Allen Jun 16 '16 at 17:28
0

As Jonathan explained, you do want to test insert, among other operations. CRUD testing, in my opinion is a very healthy check for your Model that is dealing with database records. But this is more like integration testing, rather than unit testing.

In order for it to be "pure" unit test, you need to only test that particular functionality. So how do you test method that does db insert without actually inserting anything into database (or having a database, for that matter) ? Mock objects! :) Here is a similar question to yours that talk about it: How to unit test an object with database queries

Also a simple google search will help you better understand it. But bacially, you are mocking a database, or any other object that you need. For that you probably will need some external library, but that shouldn't be a problem, because mocking is a pretty common thing nowadays. Some helpful links:

https://msdn.microsoft.com/en-ca/library/ff650441.aspx

https://en.wikipedia.org/wiki/Mock_object

Good Luck!

Community
  • 1
  • 1
Roman
  • 1,727
  • 1
  • 20
  • 28
  • yes I don't want to kinda do integration test on that, somebody else in the past has written the actual insert code stuff so I am just doing a pure unit test –  Jun 16 '16 at 17:25
  • Even with mocking the Data Access Layer, how would one avoid also doing a subsequent read operation to verify if the record was indeed added to the mock data store? The unit test to add record now depends on the implementation of reading back records. How would you address it? – Stack crashed Jan 03 '18 at 16:36
  • Responding to my own comment: Perhaps we just verify the correct interface methods from the repository was called the appropriate number of times. But it doesn't really check the code for additional faulty logic. – Stack crashed Jan 03 '18 at 16:40