4
gitpush
6y

Need help in Unit Tests,

I've reached a point where tests randomly fail, but if I run that test alone it never failed.
I do have lots of shared data between test functions of the same test class.

What options do I have?
1. Make each function responsible of seeding data into InMemory database?
2. ??? (I don't know what else I can do)

Any help is great :)

Comments
  • 3
    Non language specific makes it hard to judge.

    Execution time takes to long on some tests?

    Mock data to large.. Could you use less data to still cover the same functionality? Even if it requires mutating the test data to be correct for the next test scenario?
  • 0
    @C0D4 Sorry I wasn't clear, this is the scenario:

    1. Unit test class has private props which are the fields I use in my tests
    2. If they need to be inside database, constructor handles it
    3. (this is the problem) Some tests fail to find an inserted object, I'm not sure why, it randomly happens, but if I execute that particular test alone for many times it never fails, but if in parallel with other tests it fails.

    Check this: https://stackoverflow.com/a/...

    I'm planning to follow same approach, and I'm also using Xunit and dotnet core like that answer in SO
  • 2
    Dunno bout xunit, in junit you can have a @Before method where you can put all the data creation.
  • 2
    @gitpush I'm no C# guy but it sounds like a race condition at play somewhere.

    Could be that in parallel the db is table locked for a test and on a second concurrent insert its failing, seems like the most likely reason from where I'm sitting.
  • 1
    @ganjaman in XUnit @Before is class constructor, but I'm most probably doing what @C0D4 said, I have a race condition.

    But what if I move my data insertion code to what I showed in the link I shared earlier (https://stackoverflow.com/a/...)

    Basically what that link does, every time the function is executed, data is to be inserted to database. The upside of it:
    1. Each function can have its own InMemory database, eliminating race conditions since only one function is accessing that database.
    2. No data duplicates

    So do I go for that approach? What do you recommend?
  • 2
    I am not entirely sure, but I think one of two things might be the problem-
    1. You use something without cleaning it- a shared context between all tests. The solution for this is using proper setup and dispose(https://xunit.net/docs/...)
    2. You do clean and set everything correctly, but the db in memory points to the same memory, and then the tests affect each other. The solution for this is not running the tests in parallel
  • 3
    Most unit tests will include a destroy/dispose/after notation.

    Everything you create should be destroyed before you end up in your next set of tests.

    Adds a bit of extra work, but you could create if you haven't already , reusable methods with test data so you can invoke them to
    Create the data for you and make any changes needed in your test to adapt the data to the necessary precursor it has to be in for the tests to pass/fail.

    @hubiruchi looking at this, I would suggest using the @dispose method and cleaning up after every set of tests. This will prevent cross contamination 🤔weird word to use but it's true.
  • 2
    Another thing looking through some of those docs that may assist.

    https://xunit.net/docs/...
  • 1
    What @C0D4 said. And also look at this https://stackoverflow.com/questions...
    Have you used the same name?
  • 1
    @C0D4 Can you please explain more about reusable methods. I know what they are but how to think of writing them when thinking as test and not as reusable code

    @hubiruchi I'm sorry forgot to mention it, I use the same name for my tests I am forced to because I cannot pass a DbContextOptions instance to my repository because each function my repo initiates its own DBContext instance taken from DBContext pool, and when done it throws it back to the pool

    I hope I'm not mistaken in the approach I followed, basically it is:

    1. Data layer, all rules and methods to get the data from database

    2. Business layer: all rules and how the app should work and what is and what is not allowed.

    3. Api layer: just handles authenticating requests, checks if all params are valid then throws data to BLL, it knows nothing about what the data means and what should be done with it, it's all for BLL to handle
  • 2
    @gitpush I'll have to do some digging on Xunit to see if it's possible.

    Usuaually you would write a class that can create and return mock data for your tests.

    Say for example you were creating user records in a lot of tests, you could just call another class "testData.class" and have it generate 10+ records with slightly different setttings as required.

    Each test class constructor would only be invoking reusable code and making adjustments instead of your test setup creating all the data every time in isolation.
  • 1
    @C0D4 I understand, so I have a class that is responsible for inserting data to database, and then I just fetch. But when do I call that class? I mean all unit tests will be calling it so it is like each test function inserting its own data right?
  • 2
    @gitpush basically.

    Gives you the same sample data to work with over all tests plus lowers your need to continue writing test data all day.

    As for naming conventions, it's (in other languages anyway) usually
    MockData or TestData or something along those lines.

    Being C# you could probably import it and make it usable that way.
  • 1
    @C0D4 aha now I understand, well I better get to work then lol I'll migrate my data code to a generic class then call that class whenever needed.

    Thanks a lot man appreciate your help :D
  • 2
    @gitpush anytime.

    Fundamentals are more often then not the same across most dev'ng.
    Plus you know, it makes a nice change over the common rants 🙂
  • 1
    @C0D4 hahaha exactly, tho this type of rants usually forbidden by others but meh ...
  • 2
    @gitpush I am a rule breaker by heart so skrew em. I didn't get where I am following the rules.

    Not sure if you spot it:
    https://devrant.com/rants/2108281/...
  • 0
    @C0D4 good point 😀😀
Add Comment