Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Cannot find solution for error "Xunit.Sdk.TestClassException The following constructor parameters did not have matching fixture data: MyData myData" #3098

Open
PostalMike opened this issue Dec 20, 2024 Discussed in #3096 · 12 comments

Comments

@PostalMike
Copy link

PostalMike commented Dec 20, 2024

Discussed in #3096

Originally posted by PostalMike December 20, 2024

Hopefully have not jumped the gun, what with this only being an hour old in Discussion and then creating an issue.

I've looked over Constructor basics, etc. to try and find what's blowing this up. Nothing jumps out at me.

I REALLY need to get on with POM implementation. How XUnit is set up to work with constructors, etc. as opposed to Setup and Clean up decorated methods just isn't working. And no docs exist to make it easier to understand.

End of Preamble :) on with the issue ...

My specific error is " The following constructor parameters did not have matching fixture data: AwardsSubmitModel model, BrowserTestFixture fixture"

The hierarchy is -- My BrowserTestFixture class is inherited by the AwardsSubmitModel , which I am trying to instantiate in the constructor of my XUnit test class.

I've neatened up the constructors but no remedy rids me of this error message.

Really want to refactor my code to use Page Object Model, it appears the use of Constructors / IDispose in XUnit, vs. [Setup] and {Teardown] attributes as in NUnit / MS Test is not a smooth solution.

Here is a screen shot, forgive the mess. I'm mid process with moving code out of a class of static methods to the POM.

ConstructorIssue

The constructors, lower right to upper right and to the file on the left are for the browser fixture, then the model class inheriting it, then the test file instantiating the model.

No matter what I do to clean this up, anything added to the constructor of the test file is labeled as having conflicting fixture data, whatever the error states.

I can find a related post here: #2927 and it is great the misleading error text is being fixed in future versions. OK -- what's the bloody fix? :)

Thanks

@bradwilson
Copy link
Member

Can you provide a repro project? I don't see anywhere in your screenshots showing any fixture decorations on the test class.

Docs on shared context & fixtures: https://xunit.net/docs/shared-context

@PostalMike
Copy link
Author

PostalMike commented Dec 23, 2024

I'll try to get you a repro project today or tomorrow. Had to undo changes and go back to my static class approach. Did create a new branch for the POM but it didn't save, so I'll re-create this for you.

Re: the other issue. I can get the right indexing to read for the text boxes, just not for the kendo alert dialog buttons. If one will work and the other won't by indexing the array, but it will work with for loop, I'm thinking the issue is not with Kendo.

@PostalMike
Copy link
Author

Here you go. This is the csproj for the Se Tests with XUnit. When I run the simple text box test, I get the error "The following constructor parameters did not have matching fixture data: BrowserTestFixture browserFixture, AwardsSubmitModel submitModel"

SeleniumTests POM.zip

@bradwilson
Copy link
Member

Your test class DoITSubmitAwardShould is missing fixture declarations for BrowserTestFixture and AwardsSubmitModel, which is why xUnit1041 is firing (and why you're getting a runtime error):

image

image

You, in fact, have commented out the ICollectionFixture in your source code:

image

If you uncomment that, and add IClassFixture<AwardsSubmitModel>, then the test does run (it fails because you haven't provided the dependent project that the browser is trying to talk to, but that's the case with all the other tests as well).

@PostalMike
Copy link
Author

PostalMike commented Dec 24, 2024

Brad, I don't quite follow you here. The browser test fixture purpose is to run browser set up in common with all tests. It will log in the current user, then run tests particular to the page Recognize a Team Member. On this page with have Awards Submission, hence the Awards Submit Model, which is created to follow the Page Object Model. I'm doing 2 courses, one on Se and the other on XUnit on Pluralsight. I've removed any course notes from these files, so this clutter isn't in the files any more.

Following your input, the test code implements both the Browser Test Fixture and the Award Submit Model. This is what should happen -- the code in the Browser Test Fixture should authenticate the current user and bring up the web page. It does.

At this point, the code in the constructor of the DoITSubmitAwardShould class should run. It doesn't. I thought it was trying to run.

The last line in the code block should expose the Awards Submit form. It does do this in the non-POM code that is already working. That is, browser fixture does run up to the point where the code in this constructor should pick up the ball.

Once this constructor code runs, the test method to send "Jim" to the first name textbox should happen.

What happens is the Browser Fixture IDispose code runs. The DoITSubmitAwardShould constructor code does not run at all.

In my original non-POM code, this constructor does work. then all tests run. THEN the IDispose code runs back in the Browser Test Fixture and cleans up the test.

I've uncommented the Interface and then added the code mentioned in your instructions. Did I miss something here? At the end of the day, the _submitModel.EnterRecipientFirstName("Jim"); code in the test should call the model, which should talk to the browser and send "Jim" to the first name textbox.

This is really a forum question for the Se Course but ... if you see what I'm obviously missing and have a moment to steer me back on course ... can you help? That's not your job, so this is a big ask.

using OpenQA.Selenium;
using OpenQA.Selenium.Support.UI;
using SeleniumExtras.WaitHelpers;
using Xunit.Abstractions;
using static SeleniumTests.CommonMethods;
using SeleniumTests.PageModels;

namespace SeleniumTests
{
    public class DoITSubmitAwardShould : 
        IClassFixture<BrowserTestFixture>
        , IClassFixture<AwardsSubmitModel>
    {
        private readonly ITestOutputHelper _outputHelper;
        private readonly BrowserTestFixture _browserFixture;
        private readonly AwardsSubmitModel _submitModel;
`public DoITSubmitAwardShould(ITestOutputHelper outputHelper
    , BrowserTestFixture browserFixture, AwardsSubmitModel submitModel)
{
    _outputHelper = outputHelper;
    _browserFixture = browserFixture;
    _submitModel = submitModel;

    WebDriverWait holdOn = new WebDriverWait(_browserFixture.EdgeDriver, 
        TimeSpan.FromMilliseconds(5000));
    //Not shown in the Se course is where to get the Expected Conditions 
    //That's here
    //https://stackoverflow.com/questions/72511157/the-name-expectedconditions-does-not-exist-in-the-current-context
    //Use NuGet to install the DotNetSeleniumExtras.WaitHelpers package
    holdOn.Until(ExpectedConditions.ElementIsVisible(By.Name(RecognizeATeamMember)));
    var myEl = _browserFixture.EdgeDriver.FindElement(By.Name(RecognizeATeamMember));
    myEl.Click();
    _browserFixture.EdgeDriver.FindElement(By.LinkText(_linkTxtAwardSubmission)).Click();
}`






@bradwilson
Copy link
Member

I'm sorry, I can't really help you make the Selenium test code work. I worked to resolve your issue with the fixture objects not being available (because of the missing interfaces). I think you're going to need to find someone with Selenium experience to help you figure how to that test code should be written.

Sorry!

@PostalMike
Copy link
Author

PostalMike commented Dec 26, 2024 via email

@PostalMike
Copy link
Author

PostalMike commented Dec 26, 2024

Brad,

Since XUnit works with constructors / IDispose as opposed to test methods decorated with [Setup] and [Teardown], then this issue really is about which of these 3 classes is constructed when, yes?

That is, BrowserTestFixture.cs is all set up to generate, pre-test, what will be needed for any test case. The particular test picks up from there which submenus from the home page to work with.

The AwardsSubmitModel.cs class is now in the loop. That's the only difference.

As an old saying goes, one has to know 90% of the answer in order to ask the right question. This is from a professor at MIT known as 90% Johnson -- way before even my time. The point is, if you haven't got 9/10ths the answer already, you're lost :) and will not be asking the right questions to get the full answer.

OK -- the only change is introducing the AwardsSubmitModel.cs class, which is really just a model of the Awards Submit form, here. The top-level menu for this form is is Recognize a Team Member, that's why the 2 red highlights.

AwardsSubmitScreenshot

This class is the go between, from the Test methods to the UI.

What is up here is really not an Se issue per se, it's a tricky constructor issue, right? And massaging the constructors in all 3 of these classes is the way to make it work in XUnit, right?

If this involved Setup and Cleanup (teardown) decorators, which can do with MS Test, it would be working -- that's not a dig at you or X Unit. I'm just saying I know these will work and have used them. What I don't know is massaging constructors in X Unit to make these all play in the sandbox.

Does this detailed explanation help ring a bell on your end? Like some point of constructors I don't get, that sort of bell? It can't be a rocket science question, it has to be easy.

I'm looking over the Se Course, which covers using Se with most major testing frameworks, here is the testing frameworks slide from the course:

SeCourseTestFramkworksComparison

There is not more of an in-depth comparison involving XUnit. So on this end I'm digging into anything to get a better understanding of this.

Here is the text for the PluralSight course clip covering the framework comparisons. The implication here is it's simple to work with constructors, etc. to get the Browser Fixture, form model, test classes playing well together. The only text about working with Xunit is, as stated, a small sneak peek. I bolded and italicized the XUnit part from the course:

"NUnit is a testing framework for writing and executing tests in .NET. But besides NUnit, there are other frameworks such as xUnit, MSTest, and others. NUnit was initially created as a part of JUnit, a popular Java testing framework. It was released in early 2000s. A couple of years later in 2007, xUnit was released as an alternative to NUnit. MSTest version 1 was released with Visual Studio 2005 while the open‑source version, version 2, was released in 2016. All three frameworks have a long history in the industry and have been used for a long time. Feature‑wise, all of them provide more or less the same capabilities. One of the main differences is the used terminology. Here are the differences between the most commonly used features. In the first line, you can see attributes for marking a method as a test in each framework. On the second line, we can see that NUnit and MSTest use attributes to mark test classes. There are also differences in defining Setup and TearDown methods that run before or after all tests or before each or after each test. In xUnit, a constructor is used to execute code before each test. And executing a code once before or after all class tests requires implementing a fixture class that will be instantiated once and act as a shared context for tests. The TearDown requires implementing the IDisposable interface and the dispose method in the test or fixture class. And we can also see the difference in attribute naming when ignoring or grouping tests. We still need to touch upon many of those features. So, consider this a small sneak peek. When choosing between these three frameworks, it comes to personal preference. Action is considered the most extensible, but I find NUnit's capability of including descriptive messages to every assertion and the clarity of attribute names much more useful in my day‑to‑day work. Besides these three frameworks, there are others like SpecFlow made for behavior‑driven development, an approach that encourages teams to use conversation and concrete examples to formalize a shared understanding of how the application should behave. Let follow a specific given, and, when, then template to emphasize the user's behavior, also known as the Gherkin language. Every given, and, when, then statement is implemented to execute the stated action. And together, those actions make a test case. BDD and SpecFlow can be used with Selenium WebDriver, but remember that BDD is much more than writing tests in a particular way. It is an organizational change that requires all team members and stakeholders to collaborate. Scenarios are just the outcome of that collaboration and never the input."

Thanks!

@bradwilson
Copy link
Member

What is up here is really not an Se issue per se, it's a tricky constructor issue, right? And massaging the constructors in all 3 of these classes is the way to make it work in XUnit, right?

I think I would agree with this, and add: the way to get us to make objects for you to be passed to your constructor is to mark them as fixtures. There's no other way: if you take a constructor argument that isn't a fixture (or one of the small handful of well-known types for us like ITestOutputHelper), then you will get the error you started this post with: The following constructor parameters did not have matching fixture data.

There is no magic "we will make objects for your test class constructor" outside of fixtures. That's the only way. You also need the instance to fit into the lifetime of a fixture.

  • If you want one instance created and shared among all tests in a single class, use IClassFixture<>
  • If you want one instance created and shared among all tests in the same test collection, use ICollectionFixture<>
  • If you want one instance created and shared among all tests in the test assembly, use [assembly: AssemblyFixture].

In particular, that means if you want a new instance of an object for every test, then you need to create that object yourself in the constructor. There is no mechanism in xUnit.net to do this for you.

Hopefully this helps clarify.

@bradwilson
Copy link
Member

I don’t see why the code doesn’t work as is, though. The other code, the non-POM, works just fine.

All the other tests have a fixture declaration (as IClassFixture<>) for all their constructor arguments. Only DoITSubmitAwardShould.cs fails to follow this pattern, which is why it fails with the parameters did not have matching fixture data error.

@PostalMike
Copy link
Author

PostalMike commented Dec 31, 2024 via email

@PostalMike
Copy link
Author

PostalMike commented Jan 2, 2025 via email

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

No branches or pull requests

2 participants