Skip to main content
PI System
AFSDK
Unit Testing

Overcoming Unit Testing Challenges with OSIsoft PI: Instantiating PIPoint Objects

Explore solutions to unit testing challenges in C# applications using OSIsoft PI SDK. Learn how to instantiate PIPoint objects without a PI Server connection.

Roshan Soni

4 min read

Overcoming Unit Testing Challenges with OSIsoft PI: Instantiating PIPoint Objects

As developers working with OSIsoft PI System and AFSDK in C#, we often encounter unique challenges when introducing unit testing to applications that interact with PI Archive data. Specifically, when dealing with PIPoint objects, mocking or instantiating these objects in a test environment without an actual PI Server connection can be perplexing. This blog post explores some potential solutions and best practices for handling such scenarios.

Understanding the Challenge

PIPoint is a fundamental class within the PI SDK used to represent points (tags) on the PI Data Archive. Unfortunately, PIPoint is a sealed class with no public constructors, which means it cannot be instantiated directly via the new keyword. Additionally, PIPoint cannot be easily mocked using popular frameworks like Moq, because it is sealed and lacks virtual methods.

The main issue arises when developers want to perform unit testing that involves API calls returning PIPoint objects. In most cases, testing should avoid dependencies on external systems, such as a PI Server, to maintain test isolation and speed.

Exploring Workarounds

While the task seems daunting, there are approaches you can take to overcome these limitations:

  1. Use Existing PIPoints:

    • If your tests can tolerate some level of integration testing, consider using a well-known PIPoint, like SINUSOID, available in standard PI Systems. This approach, however, requires server connectivity and deviates from pure unit testing, so it's not ideal for all scenarios.
  2. Abstract Dependencies:

    • Designing your application with abstraction layers can effectively shield your business logic from direct PI SDK dependencies. By wrapping PIPoint and other specific library interactions into interfaces (or service classes), you can leverage dependency injection to provide mock implementations during testing.
  3. Designing Test-Friendly Systems:

    • If you are developing code from scratch or have control over the architecture, design your system in a way that expects and handles dependency injection gracefully. This practice will facilitate unit testing by allowing partial fakes or complete mock implementations when actual PIPoint instances aren’t feasible.
  4. Using a Proxy or Builder Pattern:

    • Consider implementing a factory or builder pattern that handles object creation. This design can wrap the PIPoint object creation logic and provide default behavior or substitute logic specific to the testing environment.
  5. Investigating Reflection:

    • As a last resort, advanced techniques such as using reflection to create instances of non-public constructors may be employed. This approach is fraught with maintenance challenges and potential risks related to updates of the underlying library, so exercise caution and avoid this method if possible.

Conclusion

Introducing unit testing into applications that interact with the PI System can be challenging, but with innovative architectural patterns and strategic planning, these challenges can be mitigated. By thinking critically about dependencies and leveraging design patterns that promote testability, we can foster more robust and reliable software systems.

While the PIPoint class and similar PI SDK components present unique testing challenges, embracing abstraction and designing for testability from the ground up will equip developers with the tools needed to navigate these issues. Remember, the goal of testing frameworks is not only to verify correct behavior but to do so in a way that's quick, repeatable, and independent of environmental constraints such as server availability. Happy testing!

Tags

#AFSDK
#C#
#Unit Testing
#PIPoint
#Mocking

About Roshan Soni

Expert in PI System implementation, industrial automation, and data management. Passionate about helping organizations maximize the value of their process data through innovative solutions and best practices.

Sign in to comment

Join the conversation by signing in to your account.

Comments (0)

No comments yet

Be the first to share your thoughts on this article.

Related Articles

Enhancing PI ProcessBook Trends with Banding and Zones: User Needs, Workarounds, and the Road Ahead

A look at the user demand for trend banding/zoning in OSIsoft PI ProcessBook, current VBA workarounds, UI challenges, and how future PI Vision releases aim to address these visualization needs.

Roshan Soni

Migrating PIAdvCalcFilVal Uptime Calculations from PI DataLink to PI OLEDB

Learn how to translate PI DataLink's PIAdvCalcFilVal advanced calculations—like counting uptime based on conditions—into efficient PI OLEDB SQL queries. Explore three practical approaches using PIAVG, PIINTERP, and PICOunt tables, and get tips for validation and accuracy.

Roshan Soni

Understanding PI Web API WebID Encoding: Can You Generate WebIDs Client-Side?

Curious about how PI Web API generates WebIDs and whether you can encode them client-side using GUIDs or paths? This article explores the encoding mechanisms, current documentation, and best practices for handling WebIDs in your applications.

Roshan Soni