Mockzy is a lightweight and intuitive .NET library designed to simplify the process of mocking dependencies in your unit tests. By leveraging the powerful Moq framework, Mockzy automates the creation and management of mocks for your service classes, enabling you to focus on writing effective and maintainable tests.
- Features
- Installation
- Getting Started
- API Reference
- Examples
- Best Practices
- Limitations
- Contributing
- License
- Automatic Mocking: Automatically creates mocks for all constructor dependencies of the target class.
- Easy Access: Provides straightforward methods to access and configure specific dependency mocks.
- Instance Creation: Simplifies the creation of service instances with all dependencies mocked.
- Integration with Moq: Leverages the powerful features of the Moq framework for flexible and robust mocking capabilities.
Mockzy can be easily integrated into your .NET projects via NuGet.
dotnet add package Mockzy
Install-Package Mockzy
Suppose you have a service class MyService
that depends on several interfaces:
public class MyService(
HttpClient httpClient,
ICandidateClient candidateClient,
ILookupClient lookupClient,
IMapper mapper,
IConfiguration configuration,
ILogger<ResumeParserService> logger)
// Methods to be tested...}
To create a mock instance of MyService
with all its dependencies mocked, follow these steps:
- Instantiate Mockzy:
using Mockzy;
using Moq;
var mockzy = new Mockzy<MyService>();
- Configure Specific Dependency Mocks:
// Configure the IConfiguration mock
var mockConfiguration = mockzy.GetMock<IConfiguration>();
mockConfiguration.Setup(cfg => cfg["parser:address"]).Returns("http://localhost:5000");
// Configure the HttpClient mock
var mockHttpClient = mockzy.GetMock<HttpClient>();
mockHttpClient.Setup(client => client.PostAsync(It.IsAny<string>(), It.IsAny<HttpContent>()))
.ReturnsAsync(new HttpResponseMessage(System.Net.HttpStatusCode.OK)
{
Content = new StringContent("{\"error\":null}")
});
// Configure other dependencies similarly...
After configuring the necessary mocks, you can create an instance of MyService
with all dependencies mocked:
var MyService = mockzy.CreateInstanceWithMocks();
You can now use MyService
in your tests, with all its dependencies behaving as configured in the mocks.
The Mockzy<T>
class is the core of the Mockzy library, providing functionalities to automatically mock dependencies and create instances of the target class with these mocks injected.
public Mockzy()
- Description: Initializes a new instance of the
Mockzy<T>
class. It automatically identifies and creates mocks for all constructor dependencies of the target classT
.
-
Object
public T Object { get; }
- Description: Gets the mocked instance of the target class
T
.
- Description: Gets the mocked instance of the target class
-
GetMock()
public Mock<TDependency> GetMock<TDependency>() where TDependency : class
- Description: Retrieves the mock object for a specific dependency type
TDependency
. - Returns: A
Mock<TDependency>
instance. - Exceptions: Throws
InvalidOperationException
if no mock is found for the specified type.
- Description: Retrieves the mock object for a specific dependency type
-
CreateInstanceWithMocks()
public T CreateInstanceWithMocks()
- Description: Creates an instance of the target class
T
with all its constructor dependencies injected as mocked objects. - Returns: An instance of
T
with mocked dependencies. - Exceptions: Throws
InvalidOperationException
if instance creation fails due to missing mocks or instantiation issues.
- Description: Creates an instance of the target class
Below is an example of how to use Mockzy in a unit test for the MyService
:
using Mockzy;
using Moq;
using Xunit;
public class MyServiceTests
{
[Fact]
public void ParseResumeAsync_ShouldProcessResumeCorrectly()
{
// Arrange
var mockzy = new Mockzy<MyService>();
// Configure IConfiguration mock
var mockConfiguration = mockzy.GetMock<IConfiguration>();
mockConfiguration.Setup(cfg => cfg["parser:address"]).Returns("http://localhost:5000");
// Configure HttpClient mock
var mockHttpClient = mockzy.GetMock<HttpClient>();
mockHttpClient.Setup(client => client.PostAsync(It.IsAny<string>(), It.IsAny<HttpContent>()))
.ReturnsAsync(new HttpResponseMessage(System.Net.HttpStatusCode.OK)
{
Content = new StringContent("{\"error\":null}")
});
// Configure other dependencies as needed...
var service = mockzy.CreateInstanceWithMocks();
// Act
// var result = await service.ParseResumeAsync(...);
// Assert
// Assert.NotNull(result);
// mockHttpClient.Verify(client => client.PostAsync(It.IsAny<string>(), It.IsAny<HttpContent>()), Times.Once);
}
}
In this example:
- Instantiate Mockzy: Creates a new
Mockzy<MyService>
instance, automatically mocking all constructor dependencies. - Configure Mocks: Sets up specific behaviors for the
IConfiguration
andHttpClient
mocks. - Create Service Instance: Generates an instance of
MyService
with all dependencies mocked. - Perform Assertions: Uses assertions to verify the behavior of the service and interactions with the mocks.
-
Prefer Mocking Interfaces and Abstract Classes: Mockzy automatically mocks interfaces and abstract classes. Ensure your dependencies are defined as interfaces or abstract classes to leverage this feature effectively.
-
Configure Only Necessary Mocks: Only configure the behavior of mocks that are relevant to the specific test scenario to keep tests clean and focused.
-
Use
CreateInstanceWithMocks
Wisely: Use this method to instantiate your service with all dependencies mocked. This ensures that your tests are isolated and do not rely on real implementations. -
Verify Mock Interactions: Utilize Moq's verification features to ensure that your service interacts with its dependencies as expected.
-
Concrete Class Mocking: Mockzy attempts to mock all constructor dependencies, including concrete classes. However, Moq can only effectively mock interfaces and abstract classes. For concrete classes with virtual methods, mocking is possible, but it's recommended to depend on abstractions (interfaces or abstract classes) to facilitate easier testing.
-
Complex Dependency Graphs: While Mockzy handles simple dependency injection scenarios well, highly complex or deeply nested dependencies may require additional configuration or manual intervention.
-
Constructor Selection: Mockzy selects the constructor with the most parameters by default. If your class has multiple constructors, ensure that the chosen constructor is appropriate for your testing scenario.
Contributions are welcome! Whether it's reporting bugs, suggesting features, or submitting pull requests, your input helps improve Mockzy. Please follow these steps to contribute:
-
Fork the Repository: Click the "Fork" button at the top-right corner of the repository page.
-
Clone Your Fork:
git clone https://github.com/your-username/Mockzy.git
-
Create a New Branch:
git checkout -b feature/YourFeatureName
-
Make Your Changes: Implement your feature or bug fix.
-
Commit Your Changes:
git commit -m "Add feature XYZ"
-
Push to Your Fork:
git push origin feature/YourFeatureName
-
Open a Pull Request: Navigate to the original repository and open a pull request with a description of your changes.