Unit Testing Practice with Linq to SQL

I'm trying to wrap my head around unit testing, and I came across behavior that I'm not sure about:

"Can back up"

In principle, the "Inventory" table is copied to the "InventoryHistory" table and the time stamp when the backup occurred ("HistoryDate") is set.

Here is the backup inventory code:

DateTime historyDate = DateTime.Now; MyDataContext db = new MyDataContext(); db.GetTable<InventoryHistory>().InsertAllOnSubmit( db.GetTable<Inventory>() .Select(i => new InventoryHistory { ID = i.ID, ItemName = i.ItemName, /* etc, etc, etc */ HistoryDate = historyDate }) ); 

My questions:

  • Should / Can this behavior be broken down into smaller units to be tested?

  • Since I am testing a separate test database, should I use the bullying tool and follow the abstract factory pattern for any "repositories"?

+4
source share
4 answers

The question I would ask is this really a unit test? A unit test will consider scattered instances of Table<TEntity> , because we are not interested in the actual data, rather, the mechanism for creating the elements is correct.

In your snippet above, it seems that you yourself are testing the Linq methods themselves, and not any specific code that you yourself wrote.

As for your last question, one of the fundamental mistakes made with ridicule is the assumption of what to test when it is taunted. As a rule, you will scoff at something consumed by the type you want to test. For instance:.

 public ICalculatorService { int Add(int a, int b); } [Test] public void CannAdd() { var mock = Mock<ICalculatorService(); mock.Setup(m => m.Add(It.IsAny<int>(), It.IsAny<int>())) .Returns(100); var service = mock.Object; Assert(service.Add(1, 2) == 100); // Incorrect } 

The above test is pointless because I verify that it returns exactly what I told him. I do not test the Moq environment here, I need to check my code, so I will need to test the user:

 public class Calculator { private readonly ICalculatorService _service; public Calculator(ICalculatorService service) { _service = service; } public int Add(int a, int b) { return _service.Add(a, b); } } [Test] public void CannAdd() { var mock = Mock<ICalculatorService(); mock.Setup(m => m.Add(It.IsAny<int>(), It.IsAny<int>())) .Returns(100); var calculator = new Calculator(mock.Object); Assert(calculator.Add(1, 2) == 100); // Correct } 

This is more like (albeit a simplified example). Now I am testing the consumer Calculator myself, not the consumed one. In your example, even if you mocked the DataContext to return dummy instances of Table<TEntity> , what real benefits do you get?

In fact, you are likely to create a repository, for example. a IInventoryRepository and create a user for this repository (may be a domain model, controller, etc.). Then, through testing, you will mock this repository and test your consumer.

+2
source

This seems like a pretty atomic operation to me, there are not many opportunities to break it down.

Unit testing does not affect the database - it is integration testing. If you need a good unit test for this, you will check the behavior - in this case the story will be copied when it should be.

0
source

As a full disclosure, I am just starting to study EF and LINQ and the best way to test them, so you can get more useful information about them, in particular, so these are just general test answers.

1. I see no way that this can be broken down into a unit for isolation, except:

 ID = i.ID, ItemName = i.ItemName, /* etc, etc, etc */ HistoryDate = historyDate 

It is being reorganized into a separate method for unit testing, since the only other code is the LINQ calls, which MS are responsible for testing.

2. I don’t think you can introduce a seam to isolate it with the factory abstract repository template, since you are calling in the datacontext.

I'm not sure that you need a fake (and since you will test against it, there will be a mock ) - the fake with which you are testing, the fake that you do not test is a stub ), but since it is called on the test server, you can make this an automatic integration test , since the functionality includes interaction with the data warehouse.

0
source

At first, the method you describe looks simple, and I'm not sure if it needs any unit tests. But if you want to decompose it, you can do this:

  • Retrieving a method to get a list of stocks for backup

    IQueryable GetInventoryForBackup (this DataContext) {return context.GetTable (); }

  • Extract method to convert Inventory to InventoryHistory

    IEnumerable ToInventoryHistory (this is IEnumerable, DateTime historyDate data) {return data.Select (i => new InventoryHistroy {ID = i.Id ....}

  • Extract method to save InventoryHistory sequence

    void SaveHistory (IEnumerable data) {dataContext.InsertAllOnSubmit (data); dataContext.SubmitChanges (); }

You now have exponential methods, and you can easily write unit tests for.

0
source

Source: https://habr.com/ru/post/1334965/


All Articles