Solution:
Cactus runs via a ServletRedirector and then your struts actions are executed server side.
This means the servletName of the running servlet is "ServletRedirector".
Spring, by default wants to load the servletName-servlet.xml file and you can see this by looking at ContextLoaderPlugin.getNameSpace() method.
If you set the namespace to action-servlet then you'll be fine whether in production or testing with cactus. This assumes your action servlet is mapped as 'action' in your web.xml. If it's mapped as 'bob' then it needs to be bob-servlet.xml. Actually, you could just drop the servlet because now you're specifying the namespace. I kept that for convention.
Code:
<plug-in className="org.springframework.web.struts.ContextLoaderPlugIn">
<set-property property="contextConfigLocation"
value="/WEB-INF/action-servlet.xml.xml"/>
<set-property property="namespace" value="action-servlet"/>
</plug-in>