Exploring Software Unit Testing and The Necessity Behind It with Our Proven Restful API Strategy

Posted on : 24 Feb, 05:00 PM

Software Unit Testing

Ensuring your code works properly is critical for the happiness of your customers and your business's success. According to one helpful definition, software unit testing is the key to code that works.

 

So, what is unit testing in software engineering? In computer programming, software unit testing is a method by which individual units of source code are tested in an environment to determine whether they are fit for use. A unit is the most minor possible testable software component. Usually, it performs a single cohesive function. 

 

A small unit is easier to design, execute, record, and analyze test results than more significant chunks of code are. Defects revealed by a unit test are easy to locate and repair. 

 

There are no shortcuts to successful software development. Like anything, you get out what you put in. 

 

After 28 years in the industry, we have faced many situations where we couldn't have delivered the quality our customers deserved without proper software unit testing. We know the arguments, pros, and cons well; some insist that unit testing is too difficult, time-consuming, and expensive to implement correctly. 

 

We take the opposite view. We remember plenty of situations where unit testing frameworks saved us endless hours of work and frustration. When we onboarded a client in the food processing and manufacturing industry that needed to build a mobile application for their sales team, the project was behind schedule and over budget. 

 

It was clear there were no margins for error in getting the code right. 

 

By leveraging our supply of fully trained, specialized engineers from our 4Plus1 Shadow Engineering Program, we applied hands-on methods in agile best practices and unit testing to guarantee a platform that worked successfully and exceeded the client’s expectations.

 

By going the extra mile and nailing this initial project, we locked in on continuing opportunities with this client over the past 4 years.

After repeatedly seeing the benefits of unit testing frameworks, we needed a way to make the process as streamlined and efficient as possible. That's when we envisioned building a software unit testing framework for REST API. 

 

In this article, we describe the details of this project and how we have successfully implemented a solution that makes unit testing frameworks easier to learn, more operationally efficient, and more reliable and cost-effective.

 

Unveiling the Why, How, and What of Unit Testing Frameworks

One of the biggest drivers for this project was to build a unified infrastructure for applying API unit testing. After years of trial and error, we realized there were no shortcuts to making quick code changes other than through what one engineer described as “rigorous and a test automation strategy done the right way.” We therefore identified two primary goals around the importance of software unit testing: 

 

  • Develop an efficient way to teach and train our team members, especially in the 4Plus1 program, to do API unit testing quickly and efficiently. 
  • Build a vision and test automation strategy for applying REST API testing to abstract the database layer and use the entire framework as a data access point. 

 

The key to approaching this complex task was to develop a framework for software unit testing that fulfilled three things: 

 

  • Avoid any code refactoring 
  • Abstract the database layer 
  • Establish an isolation framework

 

Following these action items and guidelines enabled us to successfully kick off the project’s first API unit testing plan. By applying unit testing to several layers independently, we were able to prove the value of this automated approach.

 

This demonstrated why an API-driven approach to software unit testing our client architectures would save time and costs and dramatically improve overall reliability and efficiency.

 

The Path That Led Our Team to Building a Unified Test Automation Strategy

The primary driver for automating our approach to unit testing frameworks was to help our team kick off new software projects on the right foot. We wanted to empower our workers with best practices to enable them to work faster and more productively.

 

By adopting a unified test automation strategy, we needed our teammates to feel empowered and use reusable components in their API unit testing process. This would produce consistency in our code base across various APIs. Ultimately, we aimed to create a cultural mind shift so that unit testing functions as an integral part of the overall software development lifecycle and not just a last-minute add-on.

 

Unit Testing Through the “Onion Architecture” 

The ability to apply unit testing frameworks for each layer separately without needing code refactoring relies on an approach described as the “Onion Architecture.” 

 

Introduced in 2008 by Jeffrey Palermo to improve testability, maintainability, and dependability, the Onion Architecture addresses the challenges faced with 3-tier and n-tier architectures. It provides a solution for common development challenges.

 

As Palermo Explains:

 

“The main premise is that it controls coupling. The fundamental rule is that all code can depend on layers more central, but code cannot depend on layers further out from the core. In other words, all coupling is toward the center.”  

Onion Architecture

The advantage of the Onion Architecture for API unit testing is that it creates a strong separation of concern (or abstraction) between the different tiers of the platform, which ultimately reduces the likelihood of testing errors. 

 

By decoupling between different tiers, developers can easily go in and test a target class without the likelihood of interfering with other parts of the code base. 

 

The diagram above illustrates the Onion Architecture, which shows how a data layer is only accessible or visible to the one layer above it – just like an “onion.” 

 

As you can see, “Repository” is only accessible to “Services,” which in turn is only accessible to “Controllers.” From a unit testing standpoint, this is very important. By using interfaces, the ability to mockup and replicate specific coding dependencies becomes much more accessible, reducing the likelihood of errors.

 

When aligned with the SOLID principles of object-oriented design, the Onion Architecture creates a robust framework for software unit testing that saves money and time across the software development lifecycle.

 

Leveraging the Moq Framework for Database Abstraction

To write our unit tests efficiently and independently without code refactoring, we adopted the open-source Moq framework for. NET. 

 

By creating what is known as “Mocks,” developers can test each code layer independently without the risks often accompanying API unit testing.

 

As Molly Alger Explains:

 

“Mock objects allow you to mimic the behavior of classes and interfaces, letting the code in the test interact with them as if they were real. This isolates the code you’re testing, ensuring that it works on its own and that no other code will make the tests fail.”

 

With Mocks, we were able to mock our component dependencies and apply the "dependency injection concept" in a way that reduced the chance of software unit testing errors, increased efficiency, and saved costs. It's definitely a win-win for the client and us!

 

In addition to our isolation framework, we needed a way to abstract our component dependencies, such as third-party mappers, to expedite our software unit testing process. Since we adopted AutoMapper as our baseline tool for object mapping, we could wrap this tool into a customized service offered through a convenient user interface. 

 

Now, the AutoMapper library is available for use or to be mocked or replaced anytime by our engineers to streamline the testing process. 

 

In addition to AutoMapper, we applied the same abstraction principle to our database layers. According to Microsoft, "When writing tests for your application, it is often desirable to avoid hitting the database." 


Entity Framework allows you to achieve this by creating a context – with behavior defined by your tests – that uses in-memory data." By adopting Microsoft's best practices, our team could write our own in-memory implementation of the components without touching the live database.

Unit Testing Frameworks

 

For example, the following diagram shows an example of using the Moq framework to construct an implementation of in-memory representation for the entity named “ResourceGroup.”

 

API Unit Testing

To achieve this, we adopted helper classes designed to implement several interfaces that set up various functions to be queried against. By handing over the in-memory data to the Moq framework context object, we could initialize the dependency injection container and register this fake Moq database context as a dependency for the repository. 

 

The key takeaway is that by creating this "Mock," we abstracted away the database and tested it against the in-memory collection without modifying it. Another approach to creating in-memory doubles with the Moq framework is to write them by hand, but this requires a lot of manual coding, which is much more time-consuming.

 

A Successful REST API Testing Build Pipeline and Extensions

By adopting the Moq framework and producing “mocks” of the in-memory collection, our team created a unit test project based on the NUnit open-source unit testing frameworks for .NET applications. We adopted the Resources API pipeline (following the entity “ResourceGroup”) to execute these unit tests. 

 

The key here is that the build pipeline would not execute if there were any faults within executed test cases. In other words, a successful API build pipeline ensured that each test worked properly. 

 

Another output our team achieved is the ability to use infrastructure classes for testing other APIs in the project that rely on the Entity Framework for data access.

 

This optimization will enable us to easily scale our unit testing efforts to different levels of client architecture within our software development lifecycle.

 

Applying Increased Unit Testing Frameworks Via Our Team 

To further assess the scope and success of our software unit testing project, we wrote API tests across three primary domains (based on the “Onion Architecture” described above):

 

1. Controller level unit tests

 

2. Service layer unit tests (located in the business layer) 

 

3. Action filter unit tests (used for validating incoming HTTP requests)

 

For example, let’s run through a quick example from the services test. First, we have managed to abstract away the database so the access layer works against the “Mock” in-memory collection. 

 

We also have a function responsible for retrieving data from the ResourceGroup entity according to specific search parameters. There are three objects in the in-memory data collection, and our unit test asserts that the function should return those three objects based on the diagram below.

REST API Testing

Sure enough, once we run the unit test, we find that the function returns three objects.

Moq Framework

The unit test shows that the output matches what we expect in real time. By isolating the framework using Moq and abstracting the database with in-memory doubles, we wrote tests within the service layer without touching any dependencies.  

 

Indeed, we have developed a more unified testing strategy that meets our vision and goals for efficiency and reliability established above.

 

 

Key Takeaways 

At Integrant, we’re passionate about developing elegant applications that exceed our customers’ expectations. Anybody can be average! We aim to provide superior services and results. 

 

Our code must work in real time every time to achieve that. To ensure the reliability of our code, we are prominent practitioners of software unit testing. 

 

In this piece, we have described our process of building a unified test automation strategy that avoids the time-consuming process of code refactoring by using the Moq framework to isolate the code, abstract the database, and create real test cases. 

 

This saves us lots of time from manually writing test code, reduces errors, and ultimately saves costs – a win-win for our customers and us. 

 

Are you seeking a reliable partner to lead your digital transformation journey? Do you have an application you want to bring to market but haven’t found the right resource? We can certainly help! 

 

Integrant brings nearly three decades of deep industry expertise to the table to ensure your project is delivered beyond your expectations. We’re obsessed with making our customers happy; if you choose to work with us, we’ll stop at nothing to over deliver on value. 

 

Call us today to schedule a demo and find out how our reliable team of expert engineers can bring your business vision to life.

 

Subscribe below or contact us to see the difference we can make. We can’t wait to get started! 

Thanks for subscribing!

Exploring Software Unit Testing and The Necessity Behind It with Our Proven Restful API Strategy

Posted on : 24 Feb, 05:00 PM

Software Unit Testing

Ensuring your code works properly is critical for the happiness of your customers and your business's success. According to one helpful definition, software unit testing is the key to code that works.

 

So, what is unit testing in software engineering? In computer programming, software unit testing is a method by which individual units of source code are tested in an environment to determine whether they are fit for use. A unit is the most minor possible testable software component. Usually, it performs a single cohesive function. 

 

A small unit is easier to design, execute, record, and analyze test results than more significant chunks of code are. Defects revealed by a unit test are easy to locate and repair. 

 

There are no shortcuts to successful software development. Like anything, you get out what you put in. 

 

After 28 years in the industry, we have faced many situations where we couldn't have delivered the quality our customers deserved without proper software unit testing. We know the arguments, pros, and cons well; some insist that unit testing is too difficult, time-consuming, and expensive to implement correctly. 

 

We take the opposite view. We remember plenty of situations where unit testing frameworks saved us endless hours of work and frustration. When we onboarded a client in the food processing and manufacturing industry that needed to build a mobile application for their sales team, the project was behind schedule and over budget. 

 

It was clear there were no margins for error in getting the code right. 

 

By leveraging our supply of fully trained, specialized engineers from our 4Plus1 Shadow Engineering Program, we applied hands-on methods in agile best practices and unit testing to guarantee a platform that worked successfully and exceeded the client’s expectations.

 

By going the extra mile and nailing this initial project, we locked in on continuing opportunities with this client over the past 4 years.

After repeatedly seeing the benefits of unit testing frameworks, we needed a way to make the process as streamlined and efficient as possible. That's when we envisioned building a software unit testing framework for REST API. 

 

In this article, we describe the details of this project and how we have successfully implemented a solution that makes unit testing frameworks easier to learn, more operationally efficient, and more reliable and cost-effective.

 

Unveiling the Why, How, and What of Unit Testing Frameworks

One of the biggest drivers for this project was to build a unified infrastructure for applying API unit testing. After years of trial and error, we realized there were no shortcuts to making quick code changes other than through what one engineer described as “rigorous and a test automation strategy done the right way.” We therefore identified two primary goals around the importance of software unit testing: 

 

  • Develop an efficient way to teach and train our team members, especially in the 4Plus1 program, to do API unit testing quickly and efficiently. 
  • Build a vision and test automation strategy for applying REST API testing to abstract the database layer and use the entire framework as a data access point. 

 

The key to approaching this complex task was to develop a framework for software unit testing that fulfilled three things: 

 

  • Avoid any code refactoring 
  • Abstract the database layer 
  • Establish an isolation framework

 

Following these action items and guidelines enabled us to successfully kick off the project’s first API unit testing plan. By applying unit testing to several layers independently, we were able to prove the value of this automated approach.

 

This demonstrated why an API-driven approach to software unit testing our client architectures would save time and costs and dramatically improve overall reliability and efficiency.

 

The Path That Led Our Team to Building a Unified Test Automation Strategy

The primary driver for automating our approach to unit testing frameworks was to help our team kick off new software projects on the right foot. We wanted to empower our workers with best practices to enable them to work faster and more productively.

 

By adopting a unified test automation strategy, we needed our teammates to feel empowered and use reusable components in their API unit testing process. This would produce consistency in our code base across various APIs. Ultimately, we aimed to create a cultural mind shift so that unit testing functions as an integral part of the overall software development lifecycle and not just a last-minute add-on.

 

Unit Testing Through the “Onion Architecture” 

The ability to apply unit testing frameworks for each layer separately without needing code refactoring relies on an approach described as the “Onion Architecture.” 

 

Introduced in 2008 by Jeffrey Palermo to improve testability, maintainability, and dependability, the Onion Architecture addresses the challenges faced with 3-tier and n-tier architectures. It provides a solution for common development challenges.

 

As Palermo Explains:

 

“The main premise is that it controls coupling. The fundamental rule is that all code can depend on layers more central, but code cannot depend on layers further out from the core. In other words, all coupling is toward the center.”  

Onion Architecture

The advantage of the Onion Architecture for API unit testing is that it creates a strong separation of concern (or abstraction) between the different tiers of the platform, which ultimately reduces the likelihood of testing errors. 

 

By decoupling between different tiers, developers can easily go in and test a target class without the likelihood of interfering with other parts of the code base. 

 

The diagram above illustrates the Onion Architecture, which shows how a data layer is only accessible or visible to the one layer above it – just like an “onion.” 

 

As you can see, “Repository” is only accessible to “Services,” which in turn is only accessible to “Controllers.” From a unit testing standpoint, this is very important. By using interfaces, the ability to mockup and replicate specific coding dependencies becomes much more accessible, reducing the likelihood of errors.

 

When aligned with the SOLID principles of object-oriented design, the Onion Architecture creates a robust framework for software unit testing that saves money and time across the software development lifecycle.

 

Leveraging the Moq Framework for Database Abstraction

To write our unit tests efficiently and independently without code refactoring, we adopted the open-source Moq framework for. NET. 

 

By creating what is known as “Mocks,” developers can test each code layer independently without the risks often accompanying API unit testing.

 

As Molly Alger Explains:

 

“Mock objects allow you to mimic the behavior of classes and interfaces, letting the code in the test interact with them as if they were real. This isolates the code you’re testing, ensuring that it works on its own and that no other code will make the tests fail.”

 

With Mocks, we were able to mock our component dependencies and apply the "dependency injection concept" in a way that reduced the chance of software unit testing errors, increased efficiency, and saved costs. It's definitely a win-win for the client and us!

 

In addition to our isolation framework, we needed a way to abstract our component dependencies, such as third-party mappers, to expedite our software unit testing process. Since we adopted AutoMapper as our baseline tool for object mapping, we could wrap this tool into a customized service offered through a convenient user interface. 

 

Now, the AutoMapper library is available for use or to be mocked or replaced anytime by our engineers to streamline the testing process. 

 

In addition to AutoMapper, we applied the same abstraction principle to our database layers. According to Microsoft, "When writing tests for your application, it is often desirable to avoid hitting the database." 


Entity Framework allows you to achieve this by creating a context – with behavior defined by your tests – that uses in-memory data." By adopting Microsoft's best practices, our team could write our own in-memory implementation of the components without touching the live database.

Unit Testing Frameworks

 

For example, the following diagram shows an example of using the Moq framework to construct an implementation of in-memory representation for the entity named “ResourceGroup.”

 

API Unit Testing

To achieve this, we adopted helper classes designed to implement several interfaces that set up various functions to be queried against. By handing over the in-memory data to the Moq framework context object, we could initialize the dependency injection container and register this fake Moq database context as a dependency for the repository. 

 

The key takeaway is that by creating this "Mock," we abstracted away the database and tested it against the in-memory collection without modifying it. Another approach to creating in-memory doubles with the Moq framework is to write them by hand, but this requires a lot of manual coding, which is much more time-consuming.

 

A Successful REST API Testing Build Pipeline and Extensions

By adopting the Moq framework and producing “mocks” of the in-memory collection, our team created a unit test project based on the NUnit open-source unit testing frameworks for .NET applications. We adopted the Resources API pipeline (following the entity “ResourceGroup”) to execute these unit tests. 

 

The key here is that the build pipeline would not execute if there were any faults within executed test cases. In other words, a successful API build pipeline ensured that each test worked properly. 

 

Another output our team achieved is the ability to use infrastructure classes for testing other APIs in the project that rely on the Entity Framework for data access.

 

This optimization will enable us to easily scale our unit testing efforts to different levels of client architecture within our software development lifecycle.

 

Applying Increased Unit Testing Frameworks Via Our Team 

To further assess the scope and success of our software unit testing project, we wrote API tests across three primary domains (based on the “Onion Architecture” described above):

 

1. Controller level unit tests

 

2. Service layer unit tests (located in the business layer) 

 

3. Action filter unit tests (used for validating incoming HTTP requests)

 

For example, let’s run through a quick example from the services test. First, we have managed to abstract away the database so the access layer works against the “Mock” in-memory collection. 

 

We also have a function responsible for retrieving data from the ResourceGroup entity according to specific search parameters. There are three objects in the in-memory data collection, and our unit test asserts that the function should return those three objects based on the diagram below.

REST API Testing

Sure enough, once we run the unit test, we find that the function returns three objects.

Moq Framework

The unit test shows that the output matches what we expect in real time. By isolating the framework using Moq and abstracting the database with in-memory doubles, we wrote tests within the service layer without touching any dependencies.  

 

Indeed, we have developed a more unified testing strategy that meets our vision and goals for efficiency and reliability established above.

 

 

Key Takeaways 

At Integrant, we’re passionate about developing elegant applications that exceed our customers’ expectations. Anybody can be average! We aim to provide superior services and results. 

 

Our code must work in real time every time to achieve that. To ensure the reliability of our code, we are prominent practitioners of software unit testing. 

 

In this piece, we have described our process of building a unified test automation strategy that avoids the time-consuming process of code refactoring by using the Moq framework to isolate the code, abstract the database, and create real test cases. 

 

This saves us lots of time from manually writing test code, reduces errors, and ultimately saves costs – a win-win for our customers and us. 

 

Are you seeking a reliable partner to lead your digital transformation journey? Do you have an application you want to bring to market but haven’t found the right resource? We can certainly help! 

 

Integrant brings nearly three decades of deep industry expertise to the table to ensure your project is delivered beyond your expectations. We’re obsessed with making our customers happy; if you choose to work with us, we’ll stop at nothing to over deliver on value. 

 

Call us today to schedule a demo and find out how our reliable team of expert engineers can bring your business vision to life.

 

Subscribe below or contact us to see the difference we can make. We can’t wait to get started! 

Thanks for subscribing!

footer-img

Integrant’s Vision is to transform the software development lifecycle through predictable results.

Subscribe

To get our newsletter & stay updated

© 2023 Integrant, Inc. All Rights Reserved | Privacy